mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 18:14:37 +08:00
update readme
This commit is contained in:
parent
ef18594f82
commit
0f3b1c1e1f
146
README-RU.md
146
README-RU.md
@ -41,7 +41,7 @@
|
||||
|
||||
</br>
|
||||
|
||||
DragonECS - это [ECS](https://en.wikipedia.org/wiki/Entity_component_system) фреймворк нацеленный на максимальную удобность, модульность, расширяемость и производительность динамического изменения сущностей. Разработан на чистом C#, без зависимостей и генерации кода. Вдохновлен [LeoEcs](https://github.com/Leopotam/ecslite).
|
||||
DragonECS - это [ECS](https://en.wikipedia.org/wiki/Entity_component_system) фреймворк нацеленный на максимальную удобность, модульность, расширяемость и производительность динамического изменения сущностей. Разработан на чистом C#, без зависимостей и генерации кода. Вдохновлен [LeoEcs Lite](https://github.com/Leopotam/ecslite).
|
||||
|
||||
> [!WARNING]
|
||||
> Проект предрелизной версии, поэтому API может меняться. В ветке main актуальная и рабочая версия.</br>
|
||||
@ -58,7 +58,7 @@ DragonECS - это [ECS](https://en.wikipedia.org/wiki/Entity_component_system)
|
||||
- [Построение](#построение)
|
||||
- [Внедрение зависимостей](#внедрение-зависимостей)
|
||||
- [Модули](#модули)
|
||||
- [Слои](#слои)
|
||||
- [Сортировка](#сортировка)
|
||||
- [Процессы](#процессы)
|
||||
- [Мир](#мир)
|
||||
- [Пул](#пул)
|
||||
@ -149,18 +149,17 @@ if (entity.TryGetID(out int entityID)) { }
|
||||
|
||||
> **NOTICE:** Сущности не могут существовать без компонентов, пустые сущности будут автоматически удаляться сразу после удаления последнего компонента либо в конце тика.
|
||||
## Component
|
||||
**Компоненты** - это данные для сущностей. Обязаны реализовывать интерфейс `IEcsComponent` или другой указывающий вид компонента.
|
||||
**Компоненты** - это данные которые крепятся к сущностям.
|
||||
```c#
|
||||
// Компоненты IEcsComponent хранятся в обычном хранилище.
|
||||
struct Health : IEcsComponent
|
||||
{
|
||||
public float health;
|
||||
public int armor;
|
||||
}
|
||||
// Компоненты с IEcsTagComponent хранятся в оптимизированном для тегов хранилище.
|
||||
struct PlayerTag : IEcsTagComponent {}
|
||||
```
|
||||
Встроенные виды компонентов:
|
||||
* `IEcsComponent` - Компоненты с данными. Универсальный тип компонентов.
|
||||
* `IEcsTagComponent` - Компоненты-теги. Без данных.
|
||||
|
||||
## System
|
||||
**Системы** - это основная логика, тут задается поведение сущностей. Существуют в виде пользовательских классов, реализующих как минимум один из интерфейсов процессов. Основные процессы:
|
||||
@ -271,8 +270,10 @@ EcsPipeline pipeline = EcsPipeline.New()
|
||||
.BuildAndInit();
|
||||
```
|
||||
|
||||
### Слои
|
||||
Очередь систем можно разбить на слои. Слой определяет место в очереди для вставки систем. Например, если необходимо чтобы какая-то система была вставлена в конце очереди, вне зависимости от места добавления, эту систему можно добавить в слой EcsConsts.END_LAYER.
|
||||
### Сортировка
|
||||
Дла управления расположением систем в пайплайне, вне зависимости от порядка добавления, есть 2 способа: Слои и Порядок сортировки.
|
||||
#### Слои
|
||||
Слой определяет место в пайплайне для вставки систем. Например, если необходимо чтобы система была вставлена в конце пайплайна, эту систему можно добавить в слой `EcsConsts.END_LAYER`.
|
||||
``` c#
|
||||
const string SOME_LAYER = nameof(SOME_LAYER);
|
||||
EcsPipeline pipeline = EcsPipeline.New()
|
||||
@ -287,9 +288,20 @@ EcsPipeline pipeline = EcsPipeline.New()
|
||||
Встроенные слои расположены в следующем порядке:
|
||||
* `EcsConst.PRE_BEGIN_LAYER`
|
||||
* `EcsConst.BEGIN_LAYER`
|
||||
* `EcsConst.BASIC_LAYER` (Если при добавлении системы не указать слой, то она будет добавлена сюда)
|
||||
* `EcsConst.BASIC_LAYER` (По умолчанию системы добавляются сюда)
|
||||
* `EcsConst.END_LAYER`
|
||||
* `EcsConst.POST_END_LAYER`
|
||||
#### Порядок сортировки
|
||||
Для сортировки систем в рамках слоя используется int значение порядка сортировки. По умолчанию системы добавляются с sortOrder = 0.
|
||||
``` c#
|
||||
EcsPipeline pipeline = EcsPipeline.New()
|
||||
// ...
|
||||
// Система SomeSystem будет вставлена в слой EcsConsts.BEGIN_LAYER
|
||||
// и расположена после систем с sortOrder меньше 10.
|
||||
.Add(New SomeSystem(), EcsConsts.BEGIN_LAYER, 10)
|
||||
// ...
|
||||
.BuildAndInit();
|
||||
```
|
||||
|
||||
## Процессы
|
||||
Процессы - это очереди систем реализующие общий интерфейс, например `IEcsRun`. Для запуска процессов используются Runner-ы. Встроенные процессы запускаются автоматически. Есть возможность реализации пользовательских процессов.
|
||||
@ -345,17 +357,20 @@ _pipeline.GetRunnerInstance<DoSomethingProcessRunner>.Do()
|
||||
</details>
|
||||
|
||||
## Мир
|
||||
Является контейнером для сущностей и компонентов.
|
||||
Контейнер для сущностей и компонентов.
|
||||
``` c#
|
||||
// Создание экземпляра мира.
|
||||
_world = new EcsDefaultWorld();
|
||||
|
||||
// Создание и удаление сущности по примеру из раздела Сущности.
|
||||
var e = _world.NewEntity();
|
||||
_world.DelEntity(e);
|
||||
```
|
||||
> **NOTICE:** Необходимо вызывать EcsWorld.Destroy() у экземпляра мира если он больше не используется, иначе он будет висеть в памяти.
|
||||
|
||||
### Конфигурация мира
|
||||
// Уничтожение мира и освобождение ресурсов. Обязательно вызывать, иначе он будет висеть в памяти.
|
||||
_world.Destroy();
|
||||
```
|
||||
> Миры изолированы друг от друга и могут обрабатываться в отдельных потоках. Но мультипоточная обработка одного мира поддерживается только при отсутсвии добавления/удаляения компонентов у сущностей.
|
||||
|
||||
Для инициализации мира сразу необходимого размера и сокращения времени прогрева, в конструктор можно передать экземпляр `EcsWorldConfig`.
|
||||
|
||||
``` c#
|
||||
@ -363,14 +378,16 @@ EcsWorldConfig config = new EcsWorldConfig(
|
||||
// Предварительно инициализирует вместимость мира для 2000 сущностей.
|
||||
entitiesCapacity: 2000,
|
||||
// Предварительно инициализирует вместимость пулов для 2000 компонентов.
|
||||
poolComponentsCapacity: 2000);
|
||||
poolComponentsCapacity: 2000
|
||||
// ... Есть и другие параметры
|
||||
);
|
||||
_world = new EcsDefaultWorld(config);
|
||||
```
|
||||
|
||||
## Пул
|
||||
Является хранилищем для компонентов, предоставляет методы для добавления/чтения/редактирования/удаления компонентов на сущности. Есть несколько видов пулов, для разных целей:
|
||||
Хранилище для компонентов, пул предоставляет методы для добавления/чтения/редактирования/удаления компонентов на сущности. Есть несколько видов пулов, для разных видов компонентов:
|
||||
* `EcsPool` - универсальный пул, хранит struct-компоненты реализующие интерфейс `IEcsComponent`;
|
||||
* `EcsTagPool` - специальный пул для пустых компонентов-тегов, хранит struct-компоненты с `IEcsTagComponent` как bool значения, что в сравнении с реализацией `EcsPool` имеет лучше оптимизацию памяти и скорости;
|
||||
* `EcsTagPool` - специальный пул, оптимизированный под компоненты-теги, хранит struct-компоненты с `IEcsTagComponent`;
|
||||
|
||||
Пулы имеют 5 основных метода и их разновидности:
|
||||
``` c#
|
||||
@ -392,12 +409,50 @@ if (poses.Has(entityID)) { /* ... */ }
|
||||
// Удалит компонент у сущности, бросит исключение если у сущности нет этого компонента.
|
||||
poses.Del(entityID);
|
||||
```
|
||||
> [!WARNING]
|
||||
> В `Release` сброке отключаются проверки на исключения.
|
||||
|
||||
> Есть "безопасные" методы, которые сначала выполнят проверку наличия/отсутствия компонента, названия таких методов начинаются с `Try`.
|
||||
|
||||
> Имеется возможность реализации пользовательского пула. Эта функция будет описана в ближайшее время.
|
||||
|
||||
## Маска
|
||||
Применяется для фильтрации сущностей по наличию или отсутствию компонентов.
|
||||
``` c#
|
||||
// Создание маски которая проверяет что у сущностей есть компоненты
|
||||
// SomeCmp1 и SomeCmp2, но нет компонента SomeCmp3.
|
||||
EcsMask mask = EcsMask.New(_world)
|
||||
// Inc - Условие наличия компонента.
|
||||
.Inc<SomeCmp1>()
|
||||
.Inc<SomeCmp2>()
|
||||
// Exc - Условие отсутствия компонента.
|
||||
.Exc<SomeCmp3>()
|
||||
.Build();
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Статическая маска</summary>
|
||||
|
||||
`EcsMask` привязаны к конкретным экземплярам мира которые необходимо передавать в `EcsMask.New(world)`, но есть `EcsStaticMask` которую можно создать без привязки к миру.
|
||||
|
||||
``` c#
|
||||
class SomeSystem : IEcsRun
|
||||
{
|
||||
// EcsStaticMask можно создавать в статических полях.
|
||||
static EcsStaticMask _staticMask = EcsStaticMask.Inc<SomeCmp1>().Inc<SomeCmp2>().Exc<SomeCmp3>().Build();
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
``` c#
|
||||
// Конвертация в обычную маску.
|
||||
EcsMask mask = _staticMask.ToMask(_world);
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Аспект
|
||||
Это пользовательские классы наследуемые от `EcsAspect` и используемые для взаимодействия с сущностями. Аспекты одновременно являются кешем пулов и маской компонентов для фильтрации сущностей. Можно рассматривать аспекты как описание того с какими сущностями работает система.
|
||||
Пользовательские классы наследуемые от `EcsAspect` и используемые для взаимодействия с сущностями. Аспекты одновременно являются кешем пулов и содержат маску. Можно рассматривать аспекты как описание того с какими сущностями работает система.
|
||||
|
||||
Упрощенный синтаксис:
|
||||
``` c#
|
||||
@ -418,7 +473,9 @@ class Aspect : EcsAspect
|
||||
}
|
||||
```
|
||||
|
||||
Явный синтаксис (результат идентичен примеру выше):
|
||||
<details>
|
||||
<summary>Явный синтаксис (результат идентичен примеру выше):</summary>
|
||||
|
||||
``` c#
|
||||
using DCFApixels.DragonECS;
|
||||
// ...
|
||||
@ -435,6 +492,8 @@ class Aspect : EcsAspect
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Комбинирование аспектов</summary>
|
||||
|
||||
@ -470,16 +529,23 @@ class Aspect : EcsAspect
|
||||
</details>
|
||||
|
||||
## Запросы
|
||||
Что бы получить необходимый набор сущностей используется метод-запрос `EcsWorld.Where<TAspect>(out TAspect aspect)`. В качестве `TAspect` указывается аспект, сущности будут отфильтрованны по маске указанного аспекта. Запрос `Where` применим как к `EcsWorld` так и коллекциям фреймворка (в этом плане Where чем-то похож на аналогичный из Linq).
|
||||
Пример:
|
||||
Фильтруют сущности и выдают коллекции сущностей удовлетворяющие определенным условиям. Встроенный запрос `Where` фильтрует на соответствие условиям маски компонентов и имеет несколько перегрузок:
|
||||
+ `EcsWorld.Where(EcsMask mask)` - Обычная фильтрация по маске;
|
||||
+ `EcsWorld.Where<TAspect>(out TAspect aspect)` - Сочетает в себе фильтрацию по маске из аспекта и получение аспекта;
|
||||
|
||||
Запрос `Where` применим как к `EcsWorld` так и коллекциям фреймворка (в этом плане Where чем-то похож на аналогичный из Linq). Так же имеются перегрузки для сортировки сущностей по `Comparison<int>`.
|
||||
|
||||
Пример системы:
|
||||
``` c#
|
||||
public class SomeDamageSystem : IEcsRun, IEcsInject<EcsDefaultWorld>
|
||||
{
|
||||
class Aspect : EcsAspect
|
||||
{
|
||||
public EcsPool<Health> healths = Inc;
|
||||
public EcsPool<DamageSignal> damageSignals = Inc;
|
||||
public EcsPool<Health> healths = Inc;
|
||||
public EcsPool<DamageSignal> damageSignals = Inc;
|
||||
public EcsTagPool<IsInvulnerable> isInvulnerables = Exc;
|
||||
// Наличие или отсутвие этого компонента не проверяется.
|
||||
public EcsTagPool<IsDiedSignal> isDiedSignals = Opt;
|
||||
}
|
||||
EcsDefaultWorld _world;
|
||||
public void Inject(EcsDefaultWorld world) => _world = world;
|
||||
@ -489,7 +555,15 @@ public class SomeDamageSystem : IEcsRun, IEcsInject<EcsDefaultWorld>
|
||||
foreach (var e in _world.Where(out Aspect a))
|
||||
{
|
||||
// Сюда попадают сущности с компонентами Health, DamageSignal и без IsInvulnerable.
|
||||
a.healths.Get(e).points -= a.damageSignals.Get(e).points;
|
||||
ref var health = ref a.healths.Get(e);
|
||||
if(health.points > 0)
|
||||
{
|
||||
health.points -= a.damageSignals.Get(e).points;
|
||||
if(health.points <= 0)
|
||||
{ // Создаем сигнал другим системам о том что сущность умерла.
|
||||
a.isDiedSignals.TryAdd(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -689,6 +763,9 @@ using DCFApixels.DragonECS;
|
||||
|
||||
// Добавляет описание типу.
|
||||
[MetaDescription("The quick brown fox jumps over the lazy dog")]
|
||||
|
||||
// Добавляет строковый уникальный идентификатор.
|
||||
[MetaID("8D56F0949201D0C84465B7A6C586DCD6")] // Строки должны быть уникальными, и не допускают символы ,<> .
|
||||
|
||||
// Добавляет строковые теги.
|
||||
[MetaTags("Tag1", "Tag2", ...)] // [MetaTags(MetaTags.HIDDEN))] чтобы скрыть в редакторе
|
||||
@ -700,17 +777,16 @@ TypeMeta typeMeta = someComponent.GetMeta();
|
||||
// или
|
||||
TypeMeta typeMeta = pool.ComponentType.ToMeta();
|
||||
|
||||
var name = typeMeta.Name;
|
||||
var color = typeMeta.Color;
|
||||
var description = typeMeta.Description;
|
||||
var group = typeMeta.Group;
|
||||
var tags = typeMeta.Tags;
|
||||
var name = typeMeta.Name; // [MetaName]
|
||||
var group = typeMeta.Group; // [MetaGroup]
|
||||
var color = typeMeta.Color; // [MetaColor]
|
||||
var description = typeMeta.Description; // [MetaDescription]
|
||||
var metaID = typeMeta.MetaID; // [MetaID]
|
||||
var tags = typeMeta.Tags; // [MetaTags]
|
||||
```
|
||||
|
||||
## EcsDebug
|
||||
Имеет набор методов для отладки и логирования. Реализован как статический класс вызывающий методы Debug-сервисов. Debug-сервисы - это посредники между системами отладки среды и EcsDebug. Это позволяет не изменяя отладочный код проекта, переносить проект на другие движки, достаточно только реализовать соответствующий Debug-сервис.
|
||||
|
||||
По умолчанию используется `DefaultDebugService` который выводит логи в консоль. Для реализации пользовательского создайте класс наследуемый от `DebugService` и реализуйте абстрактные члены класса.
|
||||
Вспомогательный тип с набором методов для отладки и логирования. Реализован как статический класс вызывающий методы Debug-сервисов. Debug-сервисы - это посредники между EcsDebug и инструментами отладки среды. Такая реализация позволяет не изменяя отладочный код, менять его поведение или переносить проект в другие среды, достаточно только реализовать соответствующий Debug-сервис.
|
||||
|
||||
``` c#
|
||||
// Вывод лога.
|
||||
@ -726,12 +802,17 @@ EcsDebug.Break();
|
||||
EcsDebug.Set<OtherDebugService>();
|
||||
```
|
||||
|
||||
> По умолчанию используется `DefaultDebugService` который выводит логи в консоль. Для реализации пользовательского создайте класс наследуемый от `DebugService` и реализуйте абстрактные члены класса.
|
||||
|
||||
> `EcsDebug` потокобезопасен, за счет того что каждый поток использует свой изолированный экземпляр сервиса. Экземпляры для потоков создаются в абстрактном методе `DebugService.CreateThreadInstance`.
|
||||
|
||||
## Профилирование
|
||||
За реализацию профайлера так же отвечает Debug-сервис. Для выделения участка кода используется `EcsProfilerMarker`;
|
||||
``` c#
|
||||
// Создание маркера с именем SomeMarker.
|
||||
private static readonly EcsProfilerMarker marker = new EcsProfilerMarker("SomeMarker");
|
||||
|
||||
...
|
||||
// ...
|
||||
|
||||
marker.Begin();
|
||||
// Код для которого замеряется скорость.
|
||||
@ -744,6 +825,7 @@ using (marker.Auto())
|
||||
// Код для которого замеряется скорость.
|
||||
}
|
||||
```
|
||||
> `DefaultDebugService` использует реализацию на основе `Stopwatch` и выводом в консоль.
|
||||
|
||||
</br>
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
</br>
|
||||
|
||||
DragonECS 是一个[实体组件系统](https://www.imooc.com/article/331544)框架。专注于提升便利性、模块性、可扩展性和动态实体修改性能。 用纯C#开发的,没有依赖和代码生成。灵感来自于[LeoEcs](https://github.com/Leopotam/ecslite)。
|
||||
DragonECS 是一个[实体组件系统](https://www.imooc.com/article/331544)框架。专注于提升便利性、模块性、可扩展性和动态实体修改性能。 用纯C#开发的,没有依赖和代码生成。灵感来自于[LeoEcs Lite](https://github.com/Leopotam/ecslite)。
|
||||
|
||||
> [!WARNING]
|
||||
> 该框架是预发布版本,因此 API 可能会有变化。在 `main` 分支中是当前的工作版本。</br>
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
</br>
|
||||
|
||||
The [ECS](https://en.wikipedia.org/wiki/Entity_component_system) Framework aims to maximize usability, modularity, extensibility and performance of dynamic entity changes. Without code generation and dependencies. Inspired by [LeoEcs](https://github.com/Leopotam/ecslite).
|
||||
The [ECS](https://en.wikipedia.org/wiki/Entity_component_system) Framework aims to maximize usability, modularity, extensibility and performance of dynamic entity changes. Without code generation and dependencies. Inspired by [LeoEcs Lite](https://github.com/Leopotam/ecslite).
|
||||
|
||||
> [!WARNING]
|
||||
> The project is a work in progress, API may change.
|
||||
|
Loading…
Reference in New Issue
Block a user