英文原文: https://github.com/mzaks/EntitasCookBook
上下文是实体的管理数据结构。实体不能单独创建,必须通过 context.CreateEntity() 创建。这样,上下文可以管理我们创建的所有实体的生命周期。它也是第一个在我们操作实体时收到通知的观察者(参见实体章节中的实体观察部分)。
为了避免垃圾回收,Entitas-CSharp 中的上下文有一个内部对象池。它包含已销毁的实体,将在用户创建新实体时使用。这样堆上的内存就会被回收。只有当我们可以确定没有人再持有对该实体的引用时,才能回收实体。这就是 Entitas-CSharp 具有内部引用计数机制的原因。如果您仅使用库存的 Entitas 并且不持有任何对您自己的实体的引用,则您不必考虑它。内部类已经为您处理了所有引用计数。但是,如果您想创建一个组件,例如:
class Neighbour: IComponent {
public IEntity reference;
}
或者有一个引用实体的 MonoBehaviour:
class EntityLink : MonoBehaviour {
IEntity _entity;
}
然后你需要在存储引用时调用_entity.Retain(this);。当你对这个实体不再感兴趣,或者存储引用的对象被销毁时,你不应该忘记调用_entity.Release(this);。如果你忘记调用Release,一个被破坏的实体就会被保留下来,并且永远不会被重新使用。有效地,它导致了内存泄漏,这在Entitas Visual Debugger中很容易观察到。如果你忘记调用Retain,你可能最终会得到一个实体的转世版本。这将导致非常奇怪的行为,而这是很难调试的。
顺便说一下,我们不鼓励有对另一个实体的引用的组件,以支持实体索引(见索引章节)。EntityLink现在是Entitas.Unity插件的一部分,所以如果你只需要在一个GameObject上引用一个实体,也不必担心。我们会支持你的。
如果我们将典型的关系(基于表的)数据库与 Entitas 进行比较,我们可以得出以下关联。组件是列,实体是行,上下文是表本身。现在在关系数据库中,table是由模式定义的。在 Entitas 中,它基于实现 IComponent 的类。这意味着当我们定义更多的组件类时,我们的表格会变得更宽。根据实现细节,它可能会影响内存消耗。在 Entitas-CSharp 的情况下,它实际上确实对内存消耗有影响,因为实体由 IComponents 数组支持。
为了解决不断增长的表大小,我们可以只引入另一个表。这是来自 Entitas-Csharp Wiki 的片段:
using Entitas;
using Entitas.CodeGenerator;
[Game, UI]
public class SceneComponent : IComponent
{
public Scene Value;
}
[Game]
public class Bullet
{
// Since it doesn't derive from 'IComponent'
// it will be generated as 'BulletComponent'
}
[Meta]
public struct EditorOnlyVisual
{
public bool ShowInMode;
public EditorOnlyVisual(bool show) {
this.ShowInMode = show;
}
}
组件类声明上方的注解告诉代码生成器我们想要拥有哪些上下文类型。在这个特定的示例中,我们有一个Game、Meta和 UI 上下文。正如您在 SceneComponent 中看到的,一个组件可以是多个上下文的一部分。含义 - 如果我们想再次将其投影到现实数据库心智模型上,则表格Game和表格 UI 都可以具有列Scene。
这实际上取决于您的用例。如果你有一个相当小/简单的游戏,你可以只使用一个上下文。这种方式要简单得多。你只需要记住,一个实体是由一个 Icomponents 数组支持的,这意味着它是一个指针数组,一个指针在 64 位架构上是 8 字节大。因此,如果您有 50 个组件,每个实体将至少有 400 字节大。如果您的游戏中有 100 个实体,它们将占用 40KB。现在由您决定 40KB 是否很多。如果您有数百个组件和 thausends 实体,最好开始切片。
有时,仅出于组织目的将组件分割到不同的上下文中也是有益的。您可能拥有仅在核心游戏上下文中需要的组件,以及一些仅与Meta游戏相关的组件。如果明确没有重叠,这意味着没有实体需要存储组件 A 和组件 Z,而不是将它们放在不同的“表”中更好。
与实体相同,可以观察到上下文的变化。这也是我们内部用于组(在其自己的章节中描述)和可视化调试器的内容。如果您想为 Entitas 编写一些工具,例如自定义日志记录或分析,您可以使用以下事件: