[Unity Entitas] CookBook 实体[3]

赵雅懿
2023-12-01

英文原文: https://github.com/mzaks/EntitasCookBook


  实体只是一袋组件。我们可以向实体添加组件,可以从实体中获取组件,也可以从实体中移除组件。在 Entitas-CSharp 中,有一种内部/通用方式来执行这些操作:

entity.AddComponent(index, component);
entity.GetComponent(index);
entity.RemoveComponent(index);

  我们必须使用索引,因为包是作为 IComponents 数组实现的。在 Entitas-CSharp 中,出于性能原因,我们选择使用数组。然而,有不同的实现选择使用哈希映射,使组件类型成为映射的键,组件实例成为值。在您对不方便的 API 感到不安之前,让我向您展示我们在实践中如何在 Entitas-CSharp 中添加、获取和删除组件。

假设我们有一个 PositionComponent。

public sealed class PositionComponent : IComponent {
    public IntVector2 value;
}

然后 API 如下所示:

entity.AddPosition(new IntVector2(x, y));
entity.position;
entity.RemovePosition();

  多亏了我们为 Entitas-CSharp 实现的代码生成工具,我们才获得了这个不错的 API。您可以在设备部分的代码生成章节中找到有关此主题的更多信息。


实体创建

  实体应该始终是上下文的一部分。这就是为什么我们不能直接实例化实体,而必须调用 context.CreateEntity()。上下文是监控实体生命周期的管理数据结构。您可以在上下文章节中找到有关上下文的更多详细信息。

  虽然可以创建和销毁实体,但重要的是要知道在 Entitas-CSharp 中,被销毁的实体并没有真正被销毁,而是在上下文中池化了对象。这是避免垃圾收集的性能优化。这一事实的副作用是,如果用户在自己的代码中保留对实体的引用,则必须小心。

  当一个实体被销毁时,它将被放入一个临时池中,如果它的引用计数回到 0,它就会被重用。

什么是引用计数?

  引用计数是一种内部机制,可确保实体在不再被引用之前不会被重用。为了跟踪引用,实体有两种方法:

public void Retain(object owner)

public void Release(object owner)

  当您保留对实体的引用时,您必须调用 entity.Retain(this);当需要删除引用时,调用 entity.Release(this); 很重要。这些调用增加和减少引用计数。 Entitas-CSharp 的所有内部类都尊重这种机制,你的代码也应该如此。如果您在保留对实体的引用时不调用 Retain,您最终可能会保留对已被销毁并重生为其他实体的实体的引用。如果您忘记对您保留的实体调用 Release,它将永远留在对象池中,使您的内存消耗随着时间的推移而增长。


实体观察

  一个实体有多个用户可以订阅的事件,以便对实体生命周期进行自省。以下是 Entitas-CSharp 当前实现中所有事件实体的列表:

  • OnComponentAdded
  • OnComponentRemoved
  • OnComponentReplaced
  • OnEntityReleased
  • OnDestroyEntity

  这些事件与用于监视实体的事件上下文相同。它们也可供外部使用,但我不建议直接使用它们。在典型的用例中,您宁愿拥有一个组、收集器或反应式系统(在相应的章节中描述)。然而,很高兴知道这些设施是存在的,如果你正在实施一些工具,那么特别使用它可能很重要。

 类似资料: