#разработка_на_практике
Не важно делаете вы игру на ООП или на ECS - всегда нужно контролировать порядок исполнения кода в вашей игре, хотя бы на верхнем уровне, иначе неизбежны проблемы, когда логика выполняется вперед ввода игрока (привет инпут лаги) или, например ИИ принимает решение по данным, которые уже не актуальны и тп.
✔️ Мы уже давно выработали простой и работающий подход:
думать не про выполнение отдельных механик, а про целые фазы выполнения игры, обычно их 5-10 штук.
Фазой можно назвать некоторый кусок игры который описывается логически какой-то слой выполнения игрового кадра. Внутри каждая фаза может состоять из тех или иных механик, естественно. Например фаза принятия решений ИИ, а внутри разные системы по выполнению логики ИИ, чтобы они могли принять решение о том, что делать игровым персонажам в этом кадре
Давайте, чтобы было понятнее распишу минимальный цикл, который у нас прослеживается почти в любой игре:
🔄 Синхронизация с Unity (в случае работы с ECS, с ООП обычно такого не надо).
В начале кадра надо с юнити подтянуть необходимые данные в ECS мир, потому что между кадрами могла посчитаться какая-то физика, коллизии и тп.
🕹 Ввод пользователя.
Считываем ввод пользователя в начале кадра, чтобы дальше геймплейная логика могла его обработать
🤖 Принятие решений ИИ.
Фактически считывание ввода от ИИ. Тут искуственный интеллект принимает решение о том, что надо сделает и также переводит это в некоторый ввод для геймплея
⚙️ Геймплей.
Тут идет основная симуляция: движение, бой, смерть, таймеры, абилки и тп. Тут меняется игровое состояние - всё, что реально происходит в игре, живёт тут
🎨 Презентация.
Берём итоговое состояние и отражаем его в Unity: дёргаем Animator, обновляем UI, спавним партиклы и звуки. Обычно этот слой только читает состояние и пишет в Unity - геймплейные данные она не трогает
🧹 Очистка.
Тут можно подчистить какой-то накопившийся за кадр мусор, если он есть
❓Почему порядок именно такой?
Каждая фаза готовит данные для следующей: Unity → ввод → логика → презентация → обратно в Unity. Данные текут в одну сторону - и это, наверное, самое важное правило
👀 Что это даёт?
- Когда фазы явные и зафиксированы, баги и тп. можно искать по стадиям и удобно сужать область поиска, а не бегать по всему проекту
- ИИ Агенту в 10раз проще отдавать какую-то работу, т.к. он прекрасно понимает куда что надо встраивать, может оценить порядок работы, и стабильнее делать качество
- Нет глупых логических гонок, которые надо постоянно фиксить
- Появляется что-то принципиально новое в игре, опять же это вписывается в общую концепцию. Например с мультиплеером вписывается какая-нибудь фаза синхронизация ввода, какие-то фазы или часть фазы можно вынести на сервер и тп.
- Повышается в целом понимание игровой системы, как человеком, так и агентом
- Для добавления новой механики тебе в 80% случаев достаточно просто выбрать нужную фазу (это уже фиксит многие проблемы), а оставшихся 20% надо выбрать порядок выполнения внутри своей фазы
🖥 Как это реализовать?
- В случае разработки на ECS на самом деле все просто и понятно. Располагаешь в нужном порядке системы, а сами системы упаковываешь в группы(фазы) по логике выполнения. Тут скажем так из коробки вся эта логика работы идет, я даже немножко упоминал это дело в недавнем ролике по ECS
- В случае ООП стоит завести какой-то классик типа GameLoop, который будет собирать в себя все верхнеуровневые сервисы какие у вас есть (спавнеры, классики инпута, сервис, который держит и обновляет мозги ботов и тп) и явно обновлять их работу. Обычно когда ты делаешь игрушку на ООП, то у тебя все довольно сильно завязано на событиях, что так или иначе скорее всего будет ломать порядок выполнения, но жить зачастую можно, если у тебя нет статик событий, через которые общается весь абсолютно геймплей
Мы в целом и так и так работали, собственно жить можно и так и так. Да с ECS это все нативнее получается, но там и к организации кода строже надо быть
Собственно, можно накинуть огонек, если было полезно🔥