Hexecs 0.4.0
dotnet add package Hexecs --version 0.4.0
NuGet\Install-Package Hexecs -Version 0.4.0
<PackageReference Include="Hexecs" Version="0.4.0" />
<PackageVersion Include="Hexecs" Version="0.4.0" />
<PackageReference Include="Hexecs" />
paket add Hexecs --version 0.4.0
#r "nuget: Hexecs, 0.4.0"
#:package Hexecs@0.4.0
#addin nuget:?package=Hexecs&version=0.4.0
#tool nuget:?package=Hexecs&version=0.4.0
HexECS
Привет! Это движок, имплементирующий ECS. Тут ты можешь делать многое, к чему и так привык. При этом, ты можешь чуть больше, чем обычные ECS, так как помимо ECS в библиотеке есть встроенный CQRS и DI. CQRS в связке с ECS представляется мне максимально подходящей штукой для управления состоянием сущностей через системы. DI необходим для того, чтобы всё это работало удобно.
Базовые возможности
Так как всё в этом мире завязано на "мир" (World
), то мы начнём с его создания.
var world = new WorldBuilder()
.DebugWorld() // чтобы получать больше информации в Debug-режиме
.CreateLogger(logger => logger.UseConsoleSink()); // чтобы логи выводились в консоль
.Build();
Этот код создаёт сконфигурированный объект World. Так как библиотека AOT-friendly, тут нет сканеров assembly для регистрации отдельных компонентов. Всё нужно регистрировать вручную.
Создание компонента
Компонент - это один из базовых кирпичиков ECS. Для того, чтобы системы могли наполнить сущность жизнью, сущность должна обладать признаками - компоненты и есть эти признаки.
public struct FlyComponent(int current, int max) : IActorComponent { // необходимо указать маркерный интерфейс
public int CurrentSpeed;
public int MaxSpeed;
}
Компоненты должны быть struct
, чтобы всё в вашем мире могло работать эффективно и быстро.
Например, обрабатывать в системах или обработчиках шины сообщений.
Создание сущности
В этом мире есть две сущности - Actor'ы и Asset'ы.
- Актёры - это динамичные изменяемые сущности, которые могут создаваться и удаляться, и которым можно добавлять и удалять компоненты.
- Ассеты - это сущности, которые нельзя изменить, представляющие из себя настройки мира, но которые также имеют компоненты. Единственное отличие - их нельзя создавать в процессе работы, так как они, по задумке, представляют из себя ресурсы, на основе которых будут создаваться актёры.
Создать актёра можно следующим образом:
Actor actor = world.Actors.CreateActor();
actor.Add(new FlyComponent(10, 20));
Actor<FlyComponent> typedActor = actor.As<FlyComponent>();
В последней строчку был создан т.н. "типизированный актёр" или актёр, в котором точно есть летающий компонент. Эта щепотка типизации очень важна в случаях, когда вам хотелось бы знать заранее - действительно ли актёр содержит нужный компонент. Например, в шине сообщений.
Структура Actor
и Actor<T>
предоставляют удобную обёртку для взаимодействия с актёром. Актёр всегда знает к какому ActorContext
он принадлежит и просто проксирует методы к контексту, чтобы программисту было проще.
Более привычным типом entity для классических ECS будет являться содержимое поля Actor.Id
, которое содержит в себе идентификатор актёра.
Если вам удобнее работать с ними, можно сделать так:
ActorId actorId = typedActor;
Добавление компонентов
Созданный актёр может быть создан с использованием метода world.Actors.Create()
.
В этом случае он не будет обладать компонентом FlyComponent
. Если мы не добавили его ранее, то добавим его:
actor.Add(new FlyComponent { CurrentSpeed = 5, MaxSpeed = 7 });
То, что компонент теперь принадлежит актёру можно легко проверить с помощью метода:
actor.Has<FlyComponent>(); // it's true!
Поздравляю, мы создали компонент и теперь можем его редактировать. Для этого достаточно получить ссылку на компонент и отредактировать его.
ref var component = ref actor.Get<FlyComponent>();
component.Current = 15;
Однако, в данном случае никто никогда не узнает о том, что было что-то изменено. Иногда это важно, например, чтобы держать кэш позиций некоторых актёров.
Чтобы все точно узнали, что были изменения, нужно использовать специальный метод:
var component = actor.Get<FlyComponent>(); // копируем компонент
component.Current = 15; // изменяем значение копии
actor.Update(component); // в этот момент все узнают, что что-то изменилось
Удаление компонентов
Тут всё тоже предельно просто. Представим, что у нас есть компонент Pilot
(на самом деле структура PilotComponent : IActorComponent
), который мы уже добавили к актёру-самолёту.
После того как пилот захотел спать, он покинет самолёт следующим способом:
actor.Remove<PilotComponent>();
Если пилота там не было, метод вернёт false
и мы сможем обработать это вопиющее нарушение правил полётов.
Если компонент был, то метод вернёт true
, а значит мы можем быть уверенными, что пассажиры в безопасности.
Дочерние элементы
Пассажиры! Их тоже можно создать примерно так:
Asset passengerAsset = world.GetAsset<PassengerAsset>();
Actor passenger = world.Actor.BuildActor(passengerAsset, Arg.Rent("plane", planeActor))
Мы находим ассет пассажира (вспомним, что у него есть компоненты).
Допустим, что он всего один.
На второй строке, с помощью зарегистрированных IActorBuilder
(имплементации "строителей" актёров по компонентам ассета), буквательно создаём актёра.
Кстати, если нам будет нужно, мы сможем проверить, по какому ассету был построен актёр, запросив actor.TryGetAsset
.
После создания пассажиров, мы можем в прямом смысле посадить их на самолёт. Для этого нужно воспользоваться следующим методом:
Actor<FlyComponent> plane = ...;
Actor passenger = ...;
plane.AddChild(passenger);
Если повторить это много раз, то в самолёте будут сидеть 2-400 пассажиров (в зависимости от типа самолёта, конечно).
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
0.4.0 | 142 | 6/5/2025 |