Tag
Тег — аналог компонента, но без данных: служит для маркировки сущности булевым флагом
- Внутренне унифицирован с компонентами — хранится в
Components<T>с флагомIsTag, разделяя единую инфраструктуру хранения - Хранится исключительно в виде битовой маски — нет массивов данных, минимальные затраты памяти
- Не замедляет поиск по компонентам и позволяет создавать множество тегов
- Нет хуков (
OnAdd/OnDelete) и нет enable/disable — тег либо есть, либо нет - Идеален для состояний (
IsPlayer,IsDead,NeedsUpdate), фильтрации запросов и любых булевых свойств - Представлен в виде пустой пользовательской структуры с маркер-интерфейсом
ITag - Использует те же фильтры запросов, что и компоненты (
All<>,None<>,Any<>) — отдельных фильтров для тегов нет
Пример:
public struct Unit : ITag { }
public struct Player : ITag { }
public struct IsDead : ITag { }
Требуется регистрация в мире между созданием и инициализацией
W.Create(WorldConfig.Default());
//...
W.Types()
.Tag<Unit>()
.Tag<Player>()
.Tag<IsDead>();
//...
W.Initialize();
Теги автоматически получают стабильный GUID, вычисленный из имени типа. Для переопределения GUID реализуйте интерфейс ITagConfig<T> на структуре тега. И ручная регистрация, и RegisterAll() используют его автоматически. Отслеживание изменений включается реализацией интерфейсов-маркеров — см. Отслеживание изменений:
public struct Poisoned : ITag, ITagConfig<Poisoned>,
ITrackableAdded, ITrackableDeleted {
public TagTypeConfig<Poisoned> Config() => new(
guid: new Guid("A1B2C3D4-...")
);
}
Добавление тегов:
// Добавление тега на сущность (перегрузки от 1 до 5 тегов)
// Вернёт true если тег отсутствовал и был добавлен, false если уже был
bool added = entity.Set<Unit>();
// Добавление нескольких тегов за один вызов
entity.Set<Unit, Player>();
entity.Set<Unit, Player, IsDead>();
// Также доступны перегрузки на 4 и 5 тегов
Основные операции:
// Получить количество тегов на сущности
int tagsCount = entity.TagsCount();
// Проверить наличие тега (перегрузки от 1 до 3 тегов — проверяет ВСЕ указанные)
bool hasUnit = entity.Has<Unit>();
bool hasBoth = entity.Has<Unit, Player>();
bool hasAll3 = entity.Has<Unit, Player, IsDead>();
// Проверить наличие хотя бы одного из указанных тегов (перегрузки от 2 до 3 тегов)
bool hasAny = entity.HasAny<Unit, Player>();
bool hasAny3 = entity.HasAny<Unit, Player, IsDead>();
// Удалить тег у сущности (перегрузки от 1 до 5 тегов)
// Вернёт true если тег присутствовал и был удалён, false если тега не было
// Безопасно использовать даже если тега нет
bool deleted = entity.Delete<Unit>();
entity.Delete<Unit, Player>();
// Переключить тег: если нет — добавить, если есть — удалить (перегрузки от 1 до 3 тегов)
// Вернёт true если тег был добавлен, false если был удалён
bool state = entity.Toggle<Unit>();
entity.Toggle<Unit, Player>();
// Условная установка или удаление тега по булевому значению (перегрузки от 1 до 3 тегов)
// true — тег устанавливается, false — удаляется
entity.Apply<Unit>(true);
entity.Apply<Unit, Player>(false, true); // Unit удалится, Player установится
Копирование и перемещение:
var source = W.Entity.New<Position>();
source.Set<Unit, Player>();
var target = W.Entity.New<Position>();
// Скопировать указанные теги на другую сущность (перегрузки от 1 до 5 тегов)
// Исходная сущность сохраняет свои теги
// Вернёт true (для одного тега) если тег был у источника и скопирован
bool copied = source.CopyTo<Unit>(target);
source.CopyTo<Unit, Player>(target);
// Переместить указанные теги на другую сущность (перегрузки от 1 до 5 тегов)
// Тег добавляется на target и удаляется с source
// Вернёт true (для одного тега) если тег был перемещён
bool moved = source.MoveTo<Unit>(target);
source.MoveTo<Unit, Player>(target);
Фильтры запросов:
Теги используют те же фильтры запросов, что и компоненты: All<>, None<>, Any<> и их варианты. Подробнее см. раздел Запросы.
Отладка:
// Собрать все теги сущности в список (для инспектора/отладки)
// Список очищается перед заполнением
var tags = new List<ITag>();
entity.GetAllTags(tags);