Tag

标签类似于组件,但不包含任何数据 — 用作实体上的布尔标记

  • 内部与组件统一 — 存储在 Components<T> 中并带有 IsTag 标志,共享相同的存储基础设施
  • 纯粹以位掩码形式存储 — 没有数据数组,内存开销极小
  • 不会减慢组件查询速度,可以创建大量标签
  • 没有钩子(OnAdd/OnDelete),没有 enable/disable — 标签要么存在,要么不存在
  • 非常适合状态标记(IsPlayerIsDeadNeedsUpdate)、查询过滤以及任何布尔属性
  • 以空的用户自定义结构体表示,带有 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 个标签的重载)
// 标签被添加到目标实体并从源实体删除
// 对于单个标签,如果标签已移动则返回 true
bool moved = source.MoveTo<Unit>(target);
source.MoveTo<Unit, Player>(target);

查询过滤器:

标签使用与组件相同的查询过滤器:All<>None<>Any<> 及其变体。详情请参阅查询章节。


调试:

// 将实体的所有标签收集到列表中(用于检查器/调试)
// 列表会在填充前被清除
var tags = new List<ITag>();
entity.GetAllTags(tags);

This site uses Just the Docs, a documentation theme for Jekyll.