Единственный козырь в рукаве struct — это interface, и пришло время злоупотреблять этой функцией, как никогда раньше. (Честно говоря, я вообще не трогал interface до прихода в ECS, где все сосредоточено вокруг struct )

Например, я замечаю, что в своих системах мне часто хочется удалить компонент из инжектируемой struct группы, чтобы та штука, которая служит «активатором» для «реактивной системы», ушла, не запускаясь снова, пока кто-нибудь не прикрепит реактивный компонент снова.

Я снова и снова замечал эту закономерность в своей игре. Удалите некоторый компонент с индексом i в IJob из всех сущностей, удовлетворяющих условию активации, чтобы он не запускался во второй раз. (В конце концов, все они, которые запускают эту систему, будут удалены, а не удаление — это 100% ошибка в моем дизайне.)

Мы не можем гарантировать, что в конце Execute структуры задания будет удаление (может быть, мы сможем в будущем C # 8, где мы сможем поместить реализацию по умолчанию в интерфейс, тогда мы могли бы реализовать структуру задания для этого интерфейса, чтобы получить по умолчанию Execute())

Но я все еще могу сделать это своим стилем с помощью интерфейса. Например, у меня есть эта группа для инъекции:

Я предсказываю, что во многих других системах в моей игре у меня будет такая группа с одной ComponentDataArray только для чтения только для того, чтобы убедиться, что система работает ( datas в этом случае), а затем что-то делать с ее реальными данными ( notes в в этом случае), затем, наконец, удалив компонент в datas на entities, над которым я сейчас работаю. В этой ситуации, как насчет того, чтобы создать интерфейс для вашей игры следующим образом:

Я уже получил одно преимущество: я могу убедиться, что где-то в структуре есть IReactive. Теперь пришло время реализовать интерфейс:

Атрибуты автоматического свойства доступны в C# 7.3 через [field: Attr]

Снова остерегайтесь поведения set независимо от того, действительно ли он обновляет вещь или нет. Если это не так, вам, возможно, придется создать резервное поле вручную и использовать трюки с возвратом ref, но на самом деле это не имеет значения, поскольку группа, которую вы отправляете на задание, должна быть доступна только для чтения, и вы, вероятно, все равно не можете использовать аксессор set.

Еще одно преимущество: это может быть больше ввода, но, читая заголовок структуры, мы видим, какой из них, вероятно, будет удален в системе. Обратите внимание, что это позор, я не могу использовать [ReadOnly] для свойства, пока не появится C # 7.3, который я могу вместо этого сделать [field:ReadOnly] и повлиять на поле поддержки.

Это не просто все украшения, теперь я делаю еще один метод расширения, который удаляет компонент с буфером команд:

Теперь я могу использовать его вместо RemoveComponent !

Помимо более красивого нового имени, подходящего для моей игры, см. строку с комментариями под выделенной строкой. В том, что я должен явно указать имя моего компонента в ‹› и дополнительно выкопать массив сущностей, чтобы дать ему i , где теперь мой метод расширения знает, как это сделать для меня, потому что он уверен в IReactiveInjectGroup<T>, что он содержит реактивный компонент T для удаления и массив сущностей для удаления. Нужна только группа и i.

(В качестве бонуса, с интерфейсом, если вы используете VSCode, например, переименование полей в интерфейсе с помощью F2 переименует все в вашем проекте, который правильно реализует этот интерфейс. Хорошо для рефакторинга в субботу в будущем!)

Как следует из предыдущего раздела, отправка всей группы на задание (чтобы мы могли получить interface плюсы…) требует [ReadOnly] для всей структуры, и вы должны убедиться, что это задание не записывает любые данные ни к чему в группе! И чтобы избежать проблемы с псевдонимами, убедитесь, что внутренние собственные контейнеры не отправляются в любое другое поле структуры. К счастью, я хочу сказать командному буферу удалить объект, а это «чтение».

То, что я хочу написать, может быть другой инъекционной структурой, и на этот раз я возьму только внутреннюю часть для работы.

Ничего страшного, что в своей первой системе вы можете не увидеть никакого сходства с комплектом. У меня сейчас так много «чрезвычайно многословных систем», что я не планирую возвращаться к их исправлению в ближайшее время.

Но, по крайней мере, при создании новых систем в будущем код будет постепенно превращаться в более систематизированный, многоразовый системный шаблон, созданный специально для моей собственной игры. ECS является модульной, и я думаю, что медленное создание вашей собственной настраиваемой системы важнее, чем раньше, когда мы используем только MonoBehaviours.