Entitas CookBook 翻译 - 106_Index
Index 索引
当我们想获取所有拥有Position Component 的Entity的时候,我们会创建一个Group然后遍历他。但是,如果我们只想获取某个Position上的Entity时,我们要怎么做呢?我们可以遍历所有有Position Component的Entity然后找到特定Position的Entity,或者我们可以用Index。
为了创建一个索引,我们需要给Component增加以下属性(注释):
using Entitas;
using Entitas.CodeGeneration.Attributes;
[Game]
public sealed class PositionComponent : IComponent {
[EntityIndex]
public IntVector2 value;
}
这个EntityIndex
属性会告诉我们的代码生成器,在Context上创建一个让用户能够根据IntVector2
来获取Entities的API。
这是MatchOne例子上从ProcessInputSystem
中提取出来的代码片段:
foreach (var e in _contexts.game.GetEntitiesWithPosition(
new IntVector2(input.x, input.y)
).Where(e => e.isInteractive)) {
e.isDestroyed = true;
}
在这个片段中,我们向Context请求所有所有“input”位置上的Entities并且筛选出所有interactive的Entities。
在内部,Index其实就是一个group观察者。他在context初始化的时候创建,从一开始就订阅了group变化的事件。当我们开始创建entites并且在上面增加components时,他们就会进入groups以及index会被通知到entity被增加了对应的component。我们可以使用component的值来做哈希表中的key,entity本身作为value。这样我们就建立起了一个index。当我们replace或者 remove component的时候,这个index也会被通知到,它会获取到之前的component。所以当我们在entity中replace成其他component的时候,index会从哈希表中移除旧component的key,并且接受到一个带有新的value的added event。
在Entitas-CSharp中,我们有两种内置的index。EntityIndex
以及PrimaryEntityIndex
。EntityIndex
是依靠哈希表来存储一组entity来作为值,这就意味着你可以有多个entity在同一个位置上。PrimaryEntityIndex
确保每一个key都是只与一个entity相关联。当你拥有Id
Component并且想用Id
Component来查找Entity的时候,就非常方便了。但你需要存储一个Entity的引用到另一个Entity中时,我们也推荐你使用这种方法(更多关于这方面的会在ingredience 的章节中说到)。
就像上一段中说到的,Entitas-CSharp仅仅实现了两种简单的Entity Indexing的策略。你可能会需要更多更复杂的Index来让你获取某个范围内的enitity或是拥有一个更为复杂的Index key。这种情况下呢,你可以看一看AbstractEntityIndex
类。将这本书提供给你的知识融会贯通,你应该会非常轻易地理解Index的实现并且写出自己自定义的Index。