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 字段/属性 — RegisterAll() 会按类型自动发现它(优先选择名为 Guid 的成员):

// 手动注册并设置 GUID
W.Types().Tag<Poisoned>(new TagTypeConfig<Poisoned>(guid: new Guid("A1B2C3D4-...")));

// 或声明静态字段 — RegisterAll() 会自动获取
public struct Poisoned : ITag {
    public static readonly Guid Guid = new("A1B2C3D4-...");
}

要启用标签的变更追踪,请使用带 trackAdded / trackDeleted 参数的 TagTypeConfig<T>(详见变更追踪):

W.Types().Tag<Unit>(new TagTypeConfig<Unit>(
    trackAdded: true,    // 启用添加追踪(默认 — false)
    trackDeleted: true   // 启用删除追踪(默认 — false)
));

// 带 GUID 和追踪的完整配置
W.Types().Tag<Poisoned>(new TagTypeConfig<Poisoned>(
    guid: new Guid("A1B2C3D4-..."),
    trackAdded: true,
    trackDeleted: true
));

设置标签:

// 为实体添加标签(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.