DragonECS/README-RU.md
2023-05-30 20:16:41 +08:00

14 KiB
Raw Blame History

Version GitHub

DragonECS - C# Entity Component System Framework

Languages: Русский English(WIP)

Данный ECS Фреймворк нацелен на максимальную удобность использования, модульность, расширяемость и производительность динамического изменения сущностей.

NOTICE: Проект в стадии разработки. API может меняться.

Оглавление

Установка

  • Unity-модуль

Поддерживается установка в виде Unity-модуля в при помощи добавления git-URL в PackageManager или ручного добавления в Packages/manifest.json:

https://github.com/DCFApixels/DragonECS.git 
  • В виде иходников

Фреймворк так же может быть добавлен в проект в виде исходников.

Версионирование

В DragonECS применяется следующая семантика версионирования: Просмотреть

Основные концепции

Entity

Сущности - это то к чему крепятся данные. Реализованны в виде идентификаторов, которых есть 2 вида:

  • int - однократный идентификатор, применяется в пределах одного тика. Не рекомендуется хранить int идентификаторы, в место этого используйте entlong;
  • entlong - долговременный идентификатор, содержит в себе полный набор информации для однозначной идентификации;

Component

Компоненты - это данные для сущностей. Обязаны реализовывать интерфейс IEcsComponent или другой указываюший вид компонента.

struct Health : IEcsComponent
{
    public float health;
    public int armor;
}

Встроенные виды компонентов

  • IEcsComponent - Компоненты с данными.
  • IEcsTagComponent - Компоненты-теги. Без данных.

System

Системы - это основная логика, тут задается поведение сущьностей. Существуют в виде пользовательских классов, реализующих как минимум один из IEcsInitProcess, IEcsDestroyProcess, IEcsRunProcess интерфейсов.

class UserSystem : IEcsPreInitProcess, IEcsInitProcess, IEcsRunProcess, IEcsDestroyProcess
{
    public void PreInit (EcsSession session) {
        // Будет вызван один раз в момент работы EcsSession.Init() и до срабатывания IEcsInitProcess.Init()
    }
    public void Init (EcsSession session) {
        // Будет вызван один раз в момент работы EcsSession.Init() и после срабатывания IEcsPreInitProcess.PreInit()
    }
    public void Run (EcsSession session) {
        // Будет вызван один раз в момент работы EcsSession.Run().
    }
    public void Destroy (EcsSession session) {
        // Будет вызван один раз в момент работы EcsSession.Destroy()
    }
    //Для реализации дополнительных процессов используйте Раннеры
}

Концепции фреймворка

Pipeline

Класс EcsPipeline является контейнером и двжиком систем, определяя поочередность их вызова, предоставляющий механизм для сообщений между системами и механизм внедрения зависимостей в системы.

Процесс

Процессы - это очереди систем реализующие общий интерфейс, например IEcsRunProcess. Для запуска процессов используются Runner-ы. Система ранеров и процессов может использоваться для создания реактивного поведения или для управления очередью вызова систем. Встроенные процессы вызываются автоматически, для ручного запуска испольщуйте раннеры получаемые из EcsPipeline.GetRunner().

Метод GetRunner относительно медленный, поэтому рекомендуется кешировать полученные раннеры.

Встроенные процессы:

  • IEcsPreInitProcess, IEcsInitProcess, IEcsRunProcess, IEcsDestroyProcess - процессы жизненого цикла Pipeline
  • IEcsPreInject, IEcsInject<T> - процессы системы внедрения зависимостей для Pipeline. Через них прокидываются зависимости
  • IEcsPreInitInjectProcess - Так же процесс системы внедрения зависимостей, но работает в пределах до выполнения IEcsInitProcess, сигнализирует о инициализации предварительных внедрений и окончании.

Пользовательские Раннеры и Процессы

Для добавления нового процесса создайте интерфейс наследованный от IEcsSystem и создайте раннер для него. Раннеры это классы реализующие интерфейс запускаемого процесса и наследуемые от EcsRunner. Пример реализации раннера для IEcsRunProcess:

public sealed class EcsRunRunner : EcsRunner<IEcsRunProcess>, IEcsRunProcess
{
   public void Run(EcsSession session)
   {
       foreach (var item in targets) item.Run(session);
   }
}

Раннеры имеют ряд требований к реализации:

  • Для одного интерфейса может быть только одна реализация раннера;
  • Наследоваться от EcsRunner<TInterface> можно только напрямую;
  • Раннер может содержать только один интерфейс(за исключением IEcsSystem);
  • Наследуемый класс EcsRunner<TInterface>, в качестве TInterface должен принимать реализованный интерфейс;
  • Раннер не может быть размещен внутри другого класса.

Мир

Является контейнером для сущностей и компонентов.

Группа

Группы это структуры данных для хранения списка сущностей и с быстрыми операциями добавления/удаления/проверки наличия и т.д. Реализованы классом EcsGroup и структурой EcsReadonlyGroup.

Пул

Является контейнером для компонентов, предоставляет методы для добавления/чтения/редактирования/удаления компонентов на сущности. Есть несколько видов пулов, для разных целей

  • EcsPool - универсальный пул, хранит struct-компоненты реализующие интерфейс IEcsComponent;
  • EcsTagPool - подходит для хранения пустых компонентов-тегов, в сравнении с EcsPool имеет лучше оптимизацию памяти и дейсвий с пулом, хранит в себе struct-компоненты реализующие IEcsTagComponent;

Так же имеется возможность реализации пользовательского пула

Субъект

Это классы наследуемые от EcsSubject, которые используются как посредник для взаимодейсвия с сушностями.

Запросы

Используйте метод-запрос EcsWorld.Where<TSubject>(out TSubject subject) для получения необходимого системе набора сущностей. Запросы работают в связке с субъектами, субъекты определяют ограничения запросов, результатом запроса становится группа сущностей удовлетворяющия условиям субъекта. По умолчанию запрос делает выборку из всех сущностей в мире, но так же можно сделать выборку из определенной группы сущностей, для этого используйте EcsWorld.WhereFor<TSubject>(EcsReadonlyGroup sourceGroup, out TSubject subject)

Модули

Группы систем реализующие общую фичу можно объединять в модули, и просто добавлять модули в Pipeline.

using DCFApixels.DragonECS;
class Module : IEcsModule 
{
    public void Import(EcsPipeline.Builder b) 
    {
        b.Add(new System1());
        b.Add(new System2(), EcsConsts.END_LAYER);
        b.Add(new System3());
    }
}
_pipeline = EcsPipeline.New()
    ...
    .AddModule(new Module())
    ...
    .BuildAndInit();

Рекомендации

Рекомендации по реаоизации систем

Системы делать максимально независимыми, без ссылок на другие системы.

Debug

Фреймворк предоставляет дополнительные интрументы для отладки и логирования, не зависящие от среды.

Атрибуты

В чистом виде атрибуты не имеют применения, но испольщуются в интеграциях с движками для задания отображения в отладочных интурментах и редакторах.

// Задает пользовательское название типа, по умолчанию используется имя типа.
using DCFApixels.DragonECS;
...
[DebugName("SomeComponent")] 
// Задает цвет типа в системе rgb, где каждый канал принимает занчение от 0 до 255, по умолчанию белый. 
// ВЫбрать цвет можно как вручную задав rgb значения, так и использовать заранее заготовленные цвета в enum DebugColor.
[DebugColor(DebugColor.Red)] 
// Добавляет описание типу.
[DebugDescription("The quick brown fox jumps over the lazy dog")] 
// Скрывает тип.
[DebugHide] 
public struct Component { }

EcsDebugUtility

Имеет набор методов для упрощения получения данных из Debug-Aтрибутов.

EcsDebug

Имеет набор методов для отладки и логирования. Реализован как статический класс вызывающий методы Debug-сервисов. Debug-сервисы являются посредниками между системами отладки среды и EcsDebug. Это позволяет не изменяя отладочный код проекта, переносить его на другие движки, достаточно только реализовать специальный Debug-сервис.
По умолчанию используется DefaultDebugService который выводит логи в консоль. Для реализации пользовательского создайте класс наследуемый от DebugService и реализайте абстрактные члены класса.

Расширения