索引
索引(Index)
当我们想要获取具有位置组件的所有实体时,我们创建一个组并在其中进行迭代。然而,在我们想要获取特定位置上的实体的情况下,该怎么办呢?我们可以迭代具有位置的所有实体,并仅收集具有所需位置的实体。或者,我们可以使用索引。
要创建索引,我们必须将组件值进行注释,如下所示:
using Entitas;
using Entitas.CodeGeneration.Attributes;
[Game]
public sealed class PositionComponent : IComponent {
[EntityIndex]
public IntVector2 value;
}
EntityIndex
注释会告诉代码生成器在上下文上创建 API,以便用户能够根据给定的 IntVector2
值获取实体。
以下是 MatchOne 中 ProcessInputSystem
的一部分代码:
foreach (var e in _contexts.game.GetEntitiesWithPosition(
new IntVector2(input.x, input.y)
).Where(e => e.isInteractive)) {
e.isDestroyed = true;
}
在此代码片段中,我们要求上下文为我们提供在“input”影响的位置上的所有实体,并过滤掉不是交互式的实体。
在内部,索引是一个组观察器。它在上下文初始化时创建,从一开始就订阅组事件。当我们开始创建实体并向其中添加组件时,它们将开始进入组,索引将被通知添加了以下组件的实体。我们可以使用组件的值作为 HashMap 中的键,其中值是实体本身。通过这种方式,我们正在建立索引。当我们替换或删除组件时,索引也会收到组的通知。它获取先前的组件,以便从 HashMap 中删除条目,并且如果我们将其替换为另一个组件,则会再次收到添加事件,其值为新值。
在 Entitas-CSharp 中,我们有两种内置索引类型。EntityIndex
和 PrimaryEntityIndex
。EntityIndex
由 HashMap 支持,该 HashMap 将实体集合存储为值。这意味着 - 您可以在相同的位置上有多个实体。PrimaryEntityIndex
确保每个键仅与一个实体关联。如果您有一个 Id
组件,并且希望通过此 Id
查找实体,那么这非常有用。这也是我们推荐的,当您需要从一个实体到另一个实体存储引用时(在“Ingredients”章节中会详细介绍)。
如前一段所述,Entitas-CSharp 仅实现了两种简单的实体索引策略。您可能需要更复杂的策略,例如在范围内获取实体,或者具有更复杂的索引键。在这种情况下,请查看 AbstractEntityIndex
类。在掌握本书提供的知识后,应该很容易理解其实现并编写自己的自定义索引。