Когда мы хотим описать конкретную систему внутри Unity с использованием LeoECS, нам необходимо описать, как именно она должна работать. Для этого нужно реализовать конкретные интерфейсы. Таких интерфейсов несколько: IEcsPreInitSystem, IEcsInitSystem, IEcsRunSystem, IEcsDestroySystem и IEcsPostDestroySystem. У каждого интерфейса есть свой метод, имеющий свой аналог в Unity. В системе можно реализовывать как от один, так и несколько интерфейсов. Каждый из них описывает сигнатуру метода, который вызывается в определенный момент кадра в последовательности PreInit, Init, Run, Destroy, PostDestroy. Если производить аналогию с юнити — это Awake, Start, Update, Destroy, соответственно, кроме разве что PostDestroy — у него нет аналога в Unity, а вызывается он в ECS после метода Destroy.
Всё никак не пойму, почему ECS вечно противопоставляют ООП, хотя в рамках ООП композиция и агрегация — это тоже вполне нормальная практика.
Наверное потому, что Richard Fabian в свое время написал книгу https://dataorienteddesign.com/dodbook/ которую почему-то, вместо описания преимуществ своего подхода, посвятил критике ООП.
В том то и дело, что это не противопоставление ООП. Это просто архитектура, которая не очень ложится на "типичное" представление о программировании и ты код пишешь "не так как раньше". И само разделение логики и данных сильно сбивает с толку на первых парах людей, не привыкших разделять логику и данные
Пример из современности — Raid: Shadow Legends. У них был неплохой доклад про переход на ECS (как минимум незнакомому с темой человеку было многое понятно)
Да, именно оттуда мы и узнали, что Raid: Shadow Legends работает на ECS
Миллениалы изобрели реляционную модель, спешите видеть ( ͡° ͜ʖ ͡°)
Пробовал я ецс, весело, увлекательно, в определенных и очень узких ситуациях супер полезно. Отличная первая ступень в мир cache-friendly кода. Но бой о бой, f тем безумцам, которые используют его для всего проекта. И большой F юнете с их мертвым по прибытию дотсом.
P.S. приятного чтения https://www.gamedev.net/blogs/entry/2265481-oop-is-dead-long-live-oop/
Спасибо, простым языком о сложном. Но тем не менее, не уверен, что я всё понял.
Я так понимаю, что вместо одного метода DealDamage(20), мы теперь:
- создаем компонент DamageEvent с параметром int hp
- когда хотим нанести вред игроку, спавним этот компонент на его сущности и выставляем параметром 20 хп
- система Health в Run() гуляет по EcsFilter<DamageEvent>, вызывает на ентити Get<HP> и там вычитает 20, а потом убирает компонент DamageEvent с сущности.
Я правильно понял? Жесть конечно.
А если надо, чтобы метод DealDamage(20) что-то возвращал, то после вычета хп, система Health должна создать какой-то евент в ответ, так что ли?
При этом если у нас много разных евентов в одной системе, то этот Run() начнет разрастаться, в итоге мы его порубим на кучу функций, и в итоге Run() будет выглядеть как длинный список if(...) method(), else if(...) method(), else if(...) method(), что не добавляет читаемости.
Выйдет что-то типа когда по сокету получаешь сообщение и у тебя огромный switch case на тип сообщения. И еще похожее в плане кучи кода видел в Defold, где нельзя вызывать напрямую методы классов, можно лишь посылать сообщения, а объект класса увидев это сообщение сам нужный метод вызовет. Вот такое же ощущение от ЕЦС. Перекладывание из одного кармана в другой, потом третий, потом чертвертый. Хотелось бы когда-нибудь пощупать, но задач таких не встречал.