Entitas CookBook 翻译 - 104_Group 组合

Group 组合

对于ECS来说,一个典型的"Hello world"就是所谓的"move system"。move system,是一个获取所有拥有Position以及Velocity组件的Entity,并且更新他们的Position 信息,让他们有效的超目标Velocity移动的System。当我们意识到这个Entity上的其他Component并不重要时,自然就会明白这个道理。这个实体可以是人,狗,汽车,直升机或房子。但如果它有一个Position组件和一个Velocity组件,它必须移动。

那我们怎么获取这些实体呢?

如Context 章节中所述,Context管理着所有实体,因此我们可以向Context请求并遍历所有Entity,从而收集具有Position以及Velocity 的那些Entites。这将是一个非常幼稚(naive)的实现。针对这种情况下,我们在Entitas中应对措施就是Group

context.GetGroup(GameMatcher.AllOf(GameMatcher.Position, GameMatcher.Velocity));

在上面的代码片中,我们要求一个Context为我们提供一个包含着所有拥有Position以及Velocity的Entities的Group。Group中包含的实体都是最新的,这意味着如果您从实体中删除某个Position,Entity就会从Group中被移除。如果您将Position和Velocity组件添加到Entity,它将直接进入该Group。

你可以任意使用Group,因为他们在内部是被重用的。Context会储存一个内部List保存所有你请求过的Group,所以如果你使用相同的Matcher访问Group,你就会获取到一个已经存在的引用。既然说到Matchers。。。

Matcher 匹配器

Matcher是我们如何描述我们感兴趣的Entity的一种方式。你可以说它就是我们的小型查询语言(query language)。 GameMatcher意味着我们有一个GameContext(请参阅Context章节中的多个Context类型部分),我们可以访问与此Context相关的所有Component类型。如果我们写context.GetGroup(GameMatcher.Position);我们会得到一组包含Position组件的Entites。为了定义更复杂的Group,我们可以使用AllOfAnyOfNoneOf方法。 “AllOf”表示所有列出的Component都必须出现在Entity中才能使此Entity成为Group的一部分;“AnyOf”表示必须存在列出的组件中的一个;而在NoneOf的情况下,我们则不希望任何列出的组件存在。 NoneOf不是一个独立的描述,这意味着你将无法编写context.GetGroup(GameMatcher.NoneOf(GameMatcher.Position));因为它会创建一个非常大的集合,所以是被禁止单独使用的。 NoneOf只能与AllOfAnyOf结合使用。

context.GetGroup(GameMatcher.AllOf(GameMatcher.Position, GameMatcher.Velocity).NoneOf(GameMatcher.NotMovable));

这样子我们就能得到一个拥有Position,Velocity但是又没有NotMovable组件的Group Of Entities了。

AllOfAnyOf 也能被组合成: context.GetGroup(Matcher.AllOf(Matcher.A, Matcher.B).AnyOf(Matcher.C, Matcher.D).NoneOf(Matcher.E))

matcher也能是从AnyOf开始的: context.GetGroup(Matcher.AnyOf(Matcher.C, Matcher.D).NoneOf(Matcher.E))

Group observation 组合的观察

就像我说过的,Group永远都是最新的,所以他会提供一个非常方便的方法让我们观察它,并且当Entity加入、移除时接收到通知。更重要的是,但我们replace(置换)一个entity上的component时,旧的component会被移除然后加上新的component。这就意味着我们的entity会暂时离开然后马上重新加入group。这就给我们的响应式编程提供一个良好的基础。

在Entitas-CSharp中,我们不会真的删除或者添加一个Component。生成出来的代码会先向用户请求新的值,触发移除component的事件,设置一个新的值给这个component,然后触发一次增加component的事件。用这个方法,我们就避免了内存的分配以及模拟了一个在使用不可修改(immutable)component的感觉。

Group里面有这几种事件可以监听:

  • OnEntityAdded
  • OnEntityRemoved
  • OnEntityUpdated

其他的原料像Collector,Index以及Reactive system都是使用这些事件。所以如果你只是日常使用的话,你完全可以直接用他们。但是如果你想制作一些自定义的东西,你可能需要了解其中的实现细节。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,026评论 19 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,975评论 6 342
  • CES设计模式从提出至今已经在诸如《守望先锋》等很多大型游戏中得到了有效的应用。在应对游戏迅速递增的复杂需求和设计...
    ZerLon51阅读 1,372评论 0 1
  • 我在风里老去 手持一个空碗 时间阻隔了我 老而弥坚 白髭须沾染风露 我用刻刀在水里 划一道泉 天井里映着浮尘点点 ...
    斯人会阅读 332评论 0 0
  • 今年的冬天感觉特别冷!又想起一个挚友说的一句话“温暖的被窝是青春的坟墓”。而我想同他说我的青春是什么? 今天早起的...
    Coco赖阅读 210评论 0 0