Skip to content

Latest commit

 

History

History
463 lines (358 loc) · 21.3 KB

README-RU.md

File metadata and controls

463 lines (358 loc) · 21.3 KB

Version GitHub Discord QQ

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

Readme Languages:

Русский

English(WIP)

Расширение добавит набор инструментов для отладки и связи с движком Unity.

Warning

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

Оглавление


Установка

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

Окружение

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

  • Зависимость: 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

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



Шаблоны

Шаблоны - это настраиваемые наборы компонентов которые можно применить к сущностям. Шаблоны должны реализовывать интерфейс 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 > Выбрать тип мира.


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.


FAQ

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

Такое иногда может происходить после обновления пакета, решается либо через Assets -> Reimport All или перезапуск окна Unity с удалением папки *project name*/Library.