Реализация отношений сущностей в виде графа. Связывающие ребра графа представлены в виде сущностей, что позволяет создавать отношения вида многие ко многим, ас помощью компонентной композиции можно настраивать вид этих отношений.
+ Игровые движки с C#: Unity, Godot, MonoGame и т.д.
Протестировано:
+ **Unity:** Минимальная версия 2020.1.0;
## Установка для Unity
* ### Unity-модуль
Поддерживается установка в виде Unity-модуля в при помощи добавления git-URL [в PackageManager](https://docs.unity3d.com/2023.2/Documentation/Manual/upm-ui-giturl.html) или ручного добавления в `Packages/manifest.json`:
Ключевой класс в котором хранится информация об отношениях. Графу требуется 2 мира: обычный мир и мир для сущностей-связей. Пример создания `EntityGraph`:
Как и обычная сущность, но регистрируется и создается в `EntityGraph`. Предназначена для данных об отношении двух сущностей.
> Отношения имеют направление, поэтому чтобы разделять сущности, далее будет использованы понятия: начальная сущность(`Start Entity`) от нее исходит сущность-связъ(`Relation Entity`) к конечной сущности(`End Entity`). Начальная и конечная сущность это сущности-узлы(`Node Entity`).
Сопоставляет сущности-связи с привязанными сущностями. Возвращает структуру `SubGraphMap` которая позволяет итерироваться по сопоставленным сущностями-связям.
```c#
// Запросом Where получем сущности-связи, потом запросом Join сопоставляем их с конечными сущностями.
// Аргумент JoinMode.End указывает что сопоставлять нужно с конечными сущностями.
foreach (var endE in map.Nodes.Where(out Aspect a))
{
// ...
// Итерация по сопоставленным сущностям-связям.
foreach (var relE in map.GetRelations(endE))
{
// ...
}
}
```
# Пример кода
Ниже приведен пример как бы могли быть реализованы системы нанесения урона взрывом и система применения урона к здоровью. Этот пример поверхностный реализации, но достаточно нагляден и демонстрирует основные функции расширения.
<details>
<summary>Использованные в примере компоненты</summary>
```c#
public struct Explosion : IEcsComponent
{
public float damage;
public float radius;
}
public struct Health : IEcsComponent
{
public float points;
}
public struct Transform : IEcsComponent
{
public Vector3 position;
}
// Компоненты для связей.
public struct DamageEvent : IEcsComponent
{
public float points;
}
public struct KillEvent : IEcsTagComponent { }
```
</details>
```c#
public class SomeExplosionHitSystem : IEcsRun, IEcsInject<EntityGraph>, IEcsInject<SpatialService>
{
class EventAspect : EcsAspect
{
public EcsPool<DamageEvent> damageEvents = Inc;
}
class Aspect : EcsAspect
{
public EcsPool<Transform> transforms = Inc;
public EcsPool<Explosion> explosions = Inc;
}
EntityGraph _graph;
SpatialService _spatial;
public void Run()
{
var relA = _graph.GraphWorld.GetAspect<EventAspect>();
foreach (var e in _graph.World.Where(out Aspect a))
{
ref var transform = ref a.transforms.Get(e);
ref var explosion = ref a.explosions.Get(e);
// Получаем все сущности рядом со взрывом.
// Реализация опущена, можно реализовать на основе Quad Tree, Spatial hashing или при помощи методов физики движка.