Единственный козырь в рукаве 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.