DragonECS-Unity/README-RU.md
2026-03-30 12:17:16 +08:00

25 KiB
Raw Blame History

Version GitHub Discord QQ

Интеграция с Unity для DragonECS

Readme Languages:

Русский

English(WIP)

Этот пакет делает работу с DragonECS в Unity более удобной и наглядной: визуальная отладка и профайлинг, редакторские шаблоны и инструменты для привязки сущностей к GameObject.

Warning

Проект в стадии разработки. API может меняться.
Readme еще не завершен, если есть не ясные моменты, вопросы можно задать тут Обратная связь

Warning

Встроенные реализации шаблонов UnityComponent<T> были перенесены СЮДА Так как некоторые модули Unity отключаемы, и например отключение модуля физики приведет к тому что код реализации UnityComponent<Rigidbody> или UnityComponent<Collider> не будет компилироваться.

//https://gist.github.com/DCFApixels/c250f2561f09e09ab3e6a4bd4f3013cb#file-unitycomponenttemplates-cs

Оглавление


Установка

Семантика версионирования - Открыть

Окружение

Обязательные требования:

  • Зависимость: DragonECS
  • Минимальная версия C# 8.0;
  • Минимальная версия Unity 2021.2.0;

Протестировано:

  • Unity: Минимальная версия 2021.2.0;

Установка для Unity

  • Unity-модуль

Поддерживается установка в виде Unity-модуля при помощи добавления git-URL в PackageManager:

https://github.com/DCFApixels/DragonECS-Unity.git

Или ручного добавления этой строчки в Packages/manifest.json:

"com.dcfa_pixels.dragonecs-unity": "https://github.com/DCFApixels/DragonECS-Unity.git",
  • В виде исходников

Можно также напрямую скопировать исходники пакета в проект.


Debug

Debug Сервис

UnityDebugService - реализация Debug-сервиса для EcsDebug. В редакторе он инициализируется автоматически и обеспечивает интеграцию: например, вызовы EcsDebug.Print направляются в консоль Unity, а EcsProfilerMarker подключается к встроенному профайлеру и т.д.

//Ручная активация.
UnityDebugService.Activate();

//Выведет сообщение в консоли Unity.
EcsDebug.Print(); 

var someMarker = new EcsProfilerMarker("SomeMarker");
someMarker.Begin();
//время выполнения этого участка будет отражено в профайлере Unity.
someMarker.End();

//Остановка игрового режима.
EcsDebug.Break();

Визуальная отладка

Реализовано в виде объектов-мониторов, в которых отображается состояние разных частей фреймворка. Найти эти мониторы можно в Play Mode в разделе DontDestroyOnLoad.

_pipeline = EcsPipeline.New()
    //...
    // Инициализация отладки для пайплайна и миров
    .AddUnityDebug(_world, _eventWorld)
    //...
    .BuildAndInit();


  • PipelineMonitor

Показывает состояние EcsPipeline. Системы отображаются в порядке их выполнения.


  • PipelineProcessMonitor

Отображает в виде матрицы процессы и системы. Системы отображаются в порядке их выполнения. Точка в пересечении системы и процесса означает что эта система является частью этого процесса.


  • WorldMonitor

Показывает состояние EcsWorld. На каждый мир, переданный в AddUnityDebug(...), создается отдельный монитор.


  • EntityMonitor

Показывает состояние сущности мира, позволяет добавлять/изменять/удалять компоненты по время Play Mode. На каждую сущность в мире создается отдельный монитор. Все мониторы сущностей помещаются в монитор мира.



Шаблоны

Интеграция содержит шаблоны, расширяющие ITemplateNode, предназначенные для настройки сущностей из редактора.

ScriptableEntityTemplate

Хранится как отдельный ассет. Наследуется от ScriptableObject.

Создать ассет: 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> { }
* Полная реализация:

Если не подходят ComponentTemplate<T> или TagComponentTemplate<T>, можно напрямую реализовать интерфейс IComponentTemplate. Например это может пригодиться для работы в связке с кастомной реализацией пула. В большинстве случаев достаточно упрощенной.

[Serializable] 
struct SomeComponent : IEcsComponent { /* ... */ }
class SomeComponentTemplate : IComponentTemplate
{
    [SerializeField]
    protected SomeComponent component;
    public Type Type { get { return typeof(SomeComponent); } }
    public bool IsUnique { get { return true; } }
    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].

Если интеграции удается найти соответствующий скрипт (по совпадению имени типа и файла, либо при наличии [MetaID]), рядом с крестиком удаления появляется иконка файла — клик выделяет скрипт в проекте, двойной клик открывает его.

При наличии атрибута [MetaDescription] показывается иконка подсказки с текстом из него.


Применение шаблонов компонентов вне стандартных шаблонов сущностей

Шаблоны компонентов можно использовать не только внутри стандартных MonoEntityTemplate и ScriptableEntityTemplate, но и в любых пользовательских классах. Для этого предусмотрены два способа:

Атрибут [ComponentTemplateReference]:

// Добавляет кнопку выбора доступной реализации IComponentTemplate
// и отображает шаблон компонента аналогично компонентам в MonoEntityTemplate или ScriptableEntityTemplate.
[SerializeReference, ComponentTemplateReference]
private IComponentTemplate _someComponent1;

Обертка ComponentTemplateProperty:

// Обертка над IComponentTemplate, аналогично примеру с атрибутом ComponentTemplateReference.
private ComponentTemplateProperty _someComponent2;

Оба подхода работают и для массивов:

[SerializeReference, ComponentTemplateReference]
private IComponentTemplate[] _components;
// или
private ComponentTemplateProperty[] _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 для Unity; собирает пайплайн из шаблонов. Наследуется от 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

Не могу повесить EcsEntityConnect или другие компоненты

Иногда это происходит после обновления пакета. Решения: выполните Assets -> Reimport All или перезапустите Unity после удаления папки Library в корне проекта.