### Наш контекст: Я разрабатываю 3D-игру в жанре RTS. Использую Unity (код на C#). Игра поделена на Core и View части. При разработке Core-части используются подходы: - Engine-Agnostic - Самописный ECS (Entity Component System). То есть, в том числе, не используется DOTS от Unity. View-часть может иметь зависимости от Core-части, но не наоборот. В игре будет огромное количество сущностей, компонентов, систем. Поэтому решение должно быть оптимальным по производительности ### Наша задача: - Разработать архитектуру - Взаимодействия Core и View части с учетом контекста. - View-части - Разработать механизм, который позволяет узнавать об изменениях ECS-компонента через отложенную реактивность. ### Учесть: - View-часть уже имеет свою архитектуру из коробки от Unity (архитектурный паттерн Entity-Component**)** ### Какие есть потребности к архитектуре: - При перемещении предмета из нефтяной вышки в инвентарь, View-часть оповещает Core об изменениях. - Core перемещает humvee через position и rotation. View нужно это отобразить. - Core создает на карте humvee, View нужно создать на карте модель транспорта. <br> <br> Как можно реализовать взаимодействие Core - View Через event-компоненты - View получает все данные через ECS-компоненты. - В одном кадре сначала выполняется Core, а потом View (последовательность настраивается в настройках Unity-редактора). Благодаря чему, View будет реагировать моментально на изменения данных в Core - Если View нужно передать данные в Core, то View делает это через ECS-компоненты. Через Мост Данные, которые либо покадрово меняются и могут не меняться долгое время и при этом «слушателю» важно также покадрового следить за обновлениями (например, движение транспорта по карте. поля position/rotation), лучше передавать во View через события и его производные, а не через ECS-компоненты. - Почему лучше так? Слишком много телодвижений требуется, так как мы генерируем события каждый кадр, чтобы менять данные. Получается, «пушкой по воробьям» - Что подразумевается под событиями: Event, делегаты, интерфейсы - Core меняет данные в ECS-компоненте, а View подхватывает изменения через события моментально. <br> Архитектуру для View не сделать никак, потому что у нее уже есть своя архитектура. Остается только писать код под данную архитектуру. Оповещение об изменениях <br> ### Хранение данных Очень удобно работать с данными в Unity, когда они все отображаются в инспекторе (моя механика Mono). - Также, удобно, что можно на сцену бросить префаб и он будет сразу работать. Однако, есть некоторые минусы: - Данные в Unity-компонентах часто слетали при сбоях Unity-редактора. - Муторно постоянно создавать мосты для новых поле/ECS-компонентов - Данные, которые по идее должны храниться в Core, почему-то хранятся во View - При разработке серверной части игры, придется переписать хранение данных. Механику Mono можно оставить для тех случаев, когда важно всегда передавать во View значения полей для его моментальной реакции. А также поменять механику. Сделать так, чтобы данные хранились в Core, а View лишь подтягивал их. Можно сохранить возможность «бросания» на сцену префабов, создав специальный unity-компонент, который будет создавать Entity и компонентами в момент запуска игры прям в префабе (в ю-компоненте) ### Создание gameobject с Mono-компонентами Если Core хочет создать Entity, у которого есть «физическая оболочка» в 3D-мире, то как должна работать механика. Что нам нужно от View - Добавление определенного префаба на сцену (на сцене появится gameobject - К этому gameobject нужно добавить Mono, который позволит через мост View-части копировать значение некоторых полей transform (position, rotation и так далее) Что мы можем сделать: ~~К entity привязываем ECS-маркер-компонент, который говорит, что «мне нужно, чтобы View создало префаб для этого entity»~~ Можно просто создать интерфейс, который будет использовать Core, а имплементирован будет View-частью. В интерфейсе будут методы, которые позволят создать префаб и привязать необходимые компоненты-мосты. ##### Изменение меша для 3д-модели при нанесении критического урона или полного уничтожения. Создать единый monobehavior-скрипт-менеджер, который будет обрабатывать все эвент-компоненты, связанные с обновлением меша. <br> <br> Потребность в создании сконфигурированного Entity есть не только у Core, но и у View части. Если View будет обращаться к Core для создания, то Core не может просто так отдать ссылку на gameobject Core должен в любом случае этим заниматься созданием, так как он же конфигурирует сущности. <br> ##### Возможность просто закинуть префаб на сцену EntityMono2 будет вызывать EntityConfigurator. И конфигуратор уже добавит сам остальные Mono-компоненты Остальные Mono-компоненты нельзя будет добавлять напрямую. Они будут работать, только если их добавить через код. <br> <br> Можно создавать один компонент на несколько систем для простоты разработки, при условии, что эти системы предназначены для работы друг с другом. Если же, эти системы должны работать с другими системами, то они должны иметь свои компоненты, чтобы быть независимыми друг от друга. ( просто мысль записал, возможно она неправильная, нужно будет обдумать на свежую голову)