Entitas Cookbook

Entitas CookBook 翻译 - 102_Entity

2018-04-24  本文已影响0人  SkyrimWu

实体 Entity

一个Entity只是一个装满Component的容器。我们可以将Component添加到Entity中、从Entity中获取Component、也可以将一个Component从Entity上删除。在Entitas-CSharp中,有一种内部/通用的方式来执行这些操作:

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

我们必须使用索引,因为这个容器是以IComponent数组的形式实现的。在Entitas-CSharp中,我们选择使用数组是出于性能原因。然而,有些实现选择使用哈希表(HashMap),使Component类型成为Key,Component实例成为Value。

在你抱怨API太麻烦之前,让我向你展示如何在实际发开中添加、获取和删除Entitas-CSharp中的Component。

先假设我们有个Component PositionComponent

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

那么实际上的API是这样的:

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

由于我们为Entitas-CSharp实现了一套代码生成工具(Code Generator),我们最终能直接使用这个漂亮的API。你可以在“器具(Appliances)”关于“代码生成(Code Generation)”一章中找到有关此主题的更多信息。

Entity的创建

Entity应始终是Context的一部分。这就是为什么我们不能直接实例化Entity,而必须调用context.CreateEntity()。Context是一个管理型的数据结构,用于监控Entity的生命周期,你可以在Context章节中找到关于Context的更多细节。

非常重要的一点,虽然可以创建和销毁Entity,Entitas-CSharp中销毁的Entity并未真正销毁,而是在Context中被缓存了起来(pooled in the context)。这是一个避免GC的性能优化。这个优化的副作用是:如果用户在自己的代码中保留对Entity的引用,那么这个引用的使用必须额外小心。

当一个Entity被销毁时,它将被放入一个临时池中,并在引用数量是'0'的时候被重用。

什么是引用数量?

引用数量是一种内部机制,它确保Entity在不再被引用之前不会被重用。Entity有两种方法处理引用:

public void Retain(object owner)

public void Release(object owner)

当你想保持对一个Entity的引用时,你必须调用entity.Retain(this);当你需要删除引用时,调用entity.Release(this);,这是非常重要的!这些调用会增加和减少引用计数。 Entitas-CSharp的所有内部类都遵守这种机制,所以你的代码也应该如此。如果您在保留对Entity的引用的同时不调用保留(Retain),则最终可能会引用一个已被销毁并重新生成的Entity。如果您忘记在保留的Entity上调用释放(Release),它将永远停留在对象池中,从而使您的内存消耗随着时间的推移而增长。

Entity的观察模式(entity observation)

一个Entity可以有多个用户订阅的事件,反映到Entity的生命周期上。
以下是Entitas-CSharp当前中所有事件的实现列表:

这些事件是Context 用于监视Entity 的相同事件。它们也暴露在外部使用,但我不建议直接使用它们。在典型的使用案例中,您更希望拥有一个Group,一个Collector 或一个Reactive System(这些都会在下面的章节中介绍)。

不管怎么样,知道这些设施的存在是很好的事情,如果您正在实现一些自己的工具,那么使用这些内置的设施可能就会变得很重要。

上一篇下一篇

猜你喜欢

热点阅读