25 KiB
Интеграция с Unity для DragonECS
Readme Languages: | ||
Русский |
English(WIP) |
Расширение добавит набор инструментов для отладки и связи с движком Unity.
Warning
Проект в стадии разработки. API может меняться.
Readme еще не завершен, если есть не ясные моменты, вопросы можно задать тут Обратная связь
Warning
Встроенные реализации шаблоны UnityComponent были перенесены СЮДА Так как некоторые модули Unity отключаемы, и например отключение модуля физики приведет к тому что код реализации UnityComponent или UnityComponent не будет компилироваться.
//https://gist.github.com/DCFApixels/c250f2561f09e09ab3e6a4bd4f3013cb#file-unitycomponenttemplates-cs
Оглавление
- Установка
- Debug
- Шаблон Сущности
- Связь с GameObject
- World Provider
- Шаблон Пайплайна
- FixedUpdate LateUpdate
- Документация проекта
- Окно настроек
- FAQ
Установка
Семантика версионирования - Открыть
Окружение
Обязательные требования:
- Зависимость: DragonECS
- Минимальная версия C# 8.0;
- Минимальная версия Unity 2021.2.0;
Протестировано:
- Unity: Минимальная версия 2021.2.0;
Установка для Unity
-
Unity-модуль
Поддерживается установка в виде Unity-модуля в при помощи добавления git-URL в PackageManager или ручного добавления в Packages/manifest.json
:
https://github.com/DCFApixels/DragonECS-Unity.git
-
В виде исходников
Пакет так же может быть добавлен в проект в виде исходников.
Debug
Debug Модуль
Подключение модуля отладки в Unity.
EcsDefaultWorld _world = new EcsDefaultWorld();
EcsEventWorld _eventWorld = new EcsDefaultWorld();
_pipeline = EcsPipeline.New()
//...
// Подключение и инициализация отладки для миров _world и _eventWorld
.AddUnityDebug(_world, _eventWorld)
//...
.BuildAndInit();
Debug Сервис
UnityDebugService
- реализация Debug-сервиса для EcsDebug
. В редакторе по умолчанию автоматически инициализируется и связывает EcsDebug.Print
с консолью Unity, EcsProfilerMarker
c профайлером и т.д.
//Ручная активация.
UnityDebugService.Activate();
//Выведет сообщение в консоли Unity.
EcsDebug.Print();
var someMarker = new EcsProfilerMarker("SomeMarker");
someMarker.Begin();
//время выполнения этого участка будет отражено в профайлере Unity.
someMarker.End();
//Остановка игрового режима.
EcsDebug.Break();
Визуальная отладка
Выполнена в виде специальных объектов-мониторов в которых отображается состояние разных аспектов фреймворка. Найти эти мониторы можно в Play Mode в разделе DontDestroyOnLoad
.
-
PipelineMonitor
Показывает состояние EcsPipeline
. Системы отображаются в порядке их выполнения.
-
PipelineProcessMonitor
Отображает в виде матрицы процессы и системы. Системы отображаются в порядке их выполнения. Точка в пересечении системы и процесса означает что эта система является частью этого процесса.
-
WorldMonitor
Показывает состояние EcsWorld
. на каждый казанный мир создается отдельный монитор.
-
EntityMonitor
Показывает состояние сущности мира, позволяет добавлять/изменять/удалять компоненты по время Play Mode. На каждую сущность в мире создается отдельный монитор. Все мониторы сущностей помещаются в монитор мира.
Шаблон Сущности
Настраиваемый набор компонентов которые можно применить к сущностям. Шаблоны должны реализовывать интерфейс ITemplateNode
.
ITemplateNode someTemplate = /*...*/;
//...
foreach (var e in _world.Where(out Aspect a))
{
// Применение шаблона сущности.
someTemplate.Apply(e, _world.id);
}
// Применение шаблона сразу при создании сущности.
int e = _world.NewEntity(someTemplate);
По умолчанию расширение содержит 2 вида шаблонов: ScriptableEntityTemplate
, MonoEntityTemplate
.
ScriptableEntityTemplate
Хранится как отдельный ассет. Наследуется от ScriptableObject
.
Действия чтобы создать ScriptableEntityTemplate
ассет:
Создать ассет: Asset > Create > DragonECS > ScriptableEntityTemplate.
Чтобы добавить компонент в меню Add Component
Нужен Шаблон компонента. Пример:
MonoEntityTemplate
Крепится к GameObject
. Наследуется от MonoBehaviour
.
Повесить компонент: Add Component > DragonECS > MonoEntityTemplate.
Чтобы добавить компонент в меню Add Component
Нужен Шаблон компонента. Пример:
Шаблон компонента
Реализация
Чтобы компонент попал в меню Add Component
нужно реализовать шаблон компонента. Шаблоны компонента это типы реализующие IComponentTemplate
.
- Упрощенная реализация:
// Обязательно добавить [Serializable] к типу компонента.
[Serializable]
struct SomeComponent : IEcsComponent { /* ... */ }
class SomeComponentTemplate : ComponentTemplate<SomeComponent> { }
// Тоже самое но для компонентов-тегов.
[Serializable]
struct SomeTagComponent : IEcsTagComponent { }
class SomeTagComponentTemplate : TagComponentTemplate<SomeComponent> { }
* Полная реализация:
[Serializable]
struct SomeComponent : IEcsComponent { /* ... */ }
class SomeComponentTemplate : IComponentTemplate
{
[SerializeField]
protected SomeComponent component;
public Type Type { get { return typeof(SomeComponent); } }
public void Apply(int worldID, int entityID)
{
EcsWorld.GetPoolInstance<EcsPool<SomeComponent>>(worldID).TryAddOrGet(entityID) = component;
}
public object GetRaw() { return component; }
public void SetRaw(object raw) { component = (SomeComponent)raw; }
public void OnGizmos(Transform transform, IComponentTemplate.GizmosMode mode) { /*...*/ }
public void OnValidate(UnityEngine.Object obj) { /*...*/ }
}
Кастомизация отображения типов
В раскрывающемся при нажатии Add Component
меню выбора компонента поддерживается иерархическое группирование. Производится группирование на основе мета-атрибута [MetaGroup]
.
Компоненты в инспекторе по умолчанию отображаются окрашенными в случайный цвет сгенерированный на основе имени компонента, выбрать другой режим окраски можно в окне настроек фреймворка. Задать конкретный цвет можно при помощи мета-атрибута [MetaColor]
.
Если редактор смог автоматически определить связанный с компонентом скрипт, то слева от крестика удаления компонента будет иконка файла. Клик по иконке выделит файл скрипта в папке проекта, двойной клик откроет скрип для редактирования. Связанный файл ищется по сопоставлению имени типа и имени файла скрипта.
Если у компонента есть мета-атрибут [MetaDescription]
, то слева от крестика удаления компонента будет иконка подсказки, при наведении курсора покажется информация из [MetaDescription]
.
Применение шаблонов компонентов вне стандартных шаблонов сущностей
При необходимости создания пользовательского шаблона, шаблоны компонентов поддерживают отображение вне стандартных MonoEntityTemplate
и ScriptableEntityTemplate
.
// ComponentTemplateReference добавляет кнопку выбора доступной реализации IComponentTemplate
// и отображает шаблон компонента аналогично компонентам в MonoEntityTemplate или ScriptableEntityTemplate.
[SerializeReference, ComponentTemplateReference]
private IComponentTempalte _someComponent1;
// Обертка над IComponentTempalte, которая работает аналогично примеру с атрибутом ComponentTemplateReference.
private ComponentTemplateProperty _someComponent2;
// Все это работает и для массивов.
[SerializeReference, ComponentTemplateReference]
private IComponentTempalte[] _components;
Связь с GameObject
Связываются сущности и GameObject-ы с помощью коннектов. Коннекты со стороны GameObject - EcsEntityConnect
, со стороны сущности - GameObjectConnect
. EcsEntityConnect
- управляющий коннект, GameObjectConnect
- создается/удаляется автоматически.
EcsEntityConnect connect = /*...*/;
entlong entity = _world.NewEntityLong();
// Связывание сущности с GameObject.
// Автоматически добавляется GameObjectConnect в сущность
// и применяются шаблоны.
connect.ConnectWith(entity);
// Или создать без применения шаблонов.
connect.ConnectWith(entity, false);
// Отвязать.
// Автоматически удалится GameObjectConnect.
connect.Disconnect();
Повесить компонент: Add Component > DragonECS > EcsEntityConnect.
Просмотреть все компоненты связанной сущности можно развернув
RUNTIME COMPONENTS
.
На панели внизу есть вспомогательные кнопки: 1) Отвязать сущность. 2) Удалить сущность. 3) Автоматическое заполнение массива шаблонов. 4) Каскадный вызов автозаполнения для всех дочерних коннектов в иерархии.
AutoEntityCreator
автоматический создает сущность и связывает с GameObject. В инспекторе ему нужно указать EcsEntityConnect
с которым связывать сущность и Провайдер мира в котором создать сущность.
Повесить компонент: Add Component > DragonECS > AutoEntityCreator.
На панели внизу есть вспомогательные кнопки: 1) Автоматическое заполнение ссылки на коннект. 2) Каскадный вызов автозаполнения для всех дочерних экземпляров в иерархии.
World Provider
EcsWorldProvider<TWorld>
- это ScriptableObject
обертка над TWorld
, предназначенная для пробрасывания экземпляра мира и настройки через инспектор Unity. Для простых случаев достаточно будет использовать синглтон версию провайдера EcsDefaultWorldSingletonProvider
.
// Синглтон провайдер создается автоматически в папке "Assets/Resource".
EcsDefaultWorldSingletonProvider provider = EcsDefaultWorldSingletonProvider.Instance;
// ...
EcsDefaultWorld world = new EcsDefaultWorld();
// Устанавливаем экземпляр мира в провайдер.
provider.Set(world);
// ...
//Получаем экземпляр мира, если провайдер был пуст, то он создаст новый мир.
EcsDefaultWorld world = provider.Get();
EcsPipeline pipeline = EcsPipeline.New()
//...
// Внедряем в системы полученный из провайдера мир.
.Inject(world)
//...
.BuildAndInit();
Пример реализации провайдера для своего типа мира
//Пример реализации своего провайдера для пробрасывания мира своего типа
[CreateAssetMenu(fileName = nameof(EcsMyWorldProvider), menuName = EcsConsts.FRAMEWORK_NAME + "/WorldProviders/" + nameof(EcsMyWorldProvider), order = 1)]
public class EcsMyWorldProvider : EcsWorldProvider<EcsMyWorld> { }
//Пример реализации синглтон версии для мира своего типа
public class EcsMyWorldSingletonProvider : EcsWorldProvider<EcsMyWorld>
{
private static EcsMyWorldSingletonProvider _instance;
public static EcsMyWorldSingletonProvider Instance
{
get
{
if (_instance == null) { _instance = FindOrCreateSingleton<EcsMyWorldSingletonProvider>("SingletonMyWorld"); }
return _instance;
}
}
}
Создать ассет провайдера: Asset > Create > DragonECS > WorldProviders > Выбрать тип мира.
Шаблон Пайплайна
Пайплайн как и сущности можно собирать из шаблонов. Шаблоны пайплайна это модули, реализующие интерфейс IEcsModule
。
По умолчанию расширение содержит 2 вида шаблонов: ScriptablePipelineTemplate
, MonoPipelineTemplate
.
ScriptablePipelineTemplate
Хранится как отдельный ассет. Наследуется от ScriptableObject
. Действия чтобы создать ScriptableEntityTemplate
ассет: Asset > Create > DragonECS > ScriptablePipelineTemplate
.
MonoPipelineTemplate
Крепится к GameObject
. Наследуется от MonoBehaviour
. Повесить компонент: Add Component > DragonECS > MonoPipelineTemplate
.
EcsRootUnity
Упрощенная реализация Ecs Root для юнити, собирает пайплайн из шаблонов пайплайна. Наследуется от MonoBehaviour
. Чтобы повесить GameObject: Add Component > DragonECS > EcsRootUnity
.
FixedUpdate LateUpdate
using DCFApixels.DragonECS;
using UnityEngine;
public class EcsRoot : MonoBehaviour
{
private EcsPipeline _pipeline;
//...
private void Update()
{
// Стандартный Run из фреймворка.
_pipeline.Run();
}
private void FixedUpdate()
{
// Специальный Run для трансляции FixedUpdate.
_pipeline.FixedRun();
}
private void LateUpdate()
{
// Специальный Run для трансляции LateUpdate.
_pipeline.LateRun();
}
// ...
}
Документация проекта
В интеграции так же есть окно документации проекта на основе Мета-Атрибутов. Открыть документацию: Tools > DragonECS > Documentation
. Документация формируется при первом открытии окна и при нажатии кнопки Update
.
Окно настроек
В окне настроек есть несколько опций, включая возможность менять режимы отображения компонентов в инспекторе. Внизу расположены удобные переключатели для используемых в фреймворке define значения для директив процессора. Открыть документацию: Tools > DragonECS > Settings
.
Инструмент для восстановления Missing Reference
Расширение активно задействует [SerializeReference]
, у которого есть известная проблема с потерей типов при переименовании. Чтобы упростить восстановление потерянных типов имеется специальный инструмент Reference Repairer
. Он может собирать все ассеты с потерянными типами, после предоставляет окно для указания новых имен потерянны типов. Далее проведет восстановление потерянных типов в собранных ассетах. Открыть окно инструмента: Tools > DragonECS > Reference Repairer
.
Если потерянные типы были с атрибутом
[MetaID(id)]
то инструмент автоматически определит новое имя типа.
FAQ
Не могу повесить EcsEntityConncet или другие компоненты
Такое иногда может происходить после обновления пакета, решается либо через Assets -> Reimport All
или перезапуск окна Unity с удалением папки *project name*/Library
.