Entitas 五 Group 组

组(Group)

ECS 中的经典 “Hello World” 就是所谓的 “移动系统”。移动系统是一个将所有具有位置和速度组件的实体提取出来的系统,并在此实体上交换位置组件,有效地将其移向速度向量。AHA 的时刻来临时,我们意识到无论该实体上还有什么其他类型的组件,都无关紧要。它可以是一个人、狗、汽车、直升机或房屋。如果它有位置组件和速度组件,它就必须被移动。

然而,我们如何获取这些实体呢?

如上下文章节所述,上下文管理着所有的实体,因此我们可以向上下文询问所有的实体,然后遍历它们,收集那些具有位置和速度组件的实体。这将是一个非常简单的实现。在 Entitas 中,我们为此情况提供了所谓的

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

在上面的语句中,我们要求上下文为我们提供一个持有具有 PositionVelocity 组件的实体的组。组是一个始终保持最新状态的实体集合。这意味着,如果您从实体中移除一个位置组件,它将立即离开该组。如果您向实体添加位置和速度组件,它将直接进入该组。

您可以毫不犹豫地要求获取组,因为它们在内部会被重用。上下文保留了您要求的所有组的内部列表,因此如果您再次使用相同的匹配器请求一个组,它将只是给您一个对已经存在的组的引用。说到匹配器…

匹配器(Matcher)

匹配器是我们描述我们感兴趣的实体类型的方式。如果您愿意,这是我们的小查询语言。GameMatcher 表示我们有一个 Game 上下文(请参阅上下文章节中的多个上下文类型部分),并且我们可以访问与该上下文关联的所有组件类型。如果我们写 context.GetGroup(GameMatcher.Position);,我们将得到一个具有 Position 组件的实体组。为了定义更复杂的组,我们可以使用 AllOfAnyOfNoneOf 方法。AllOf 表示实体上必须存在所有列出的组件,以便该实体成为组的一部分。AnyOf 表示列出的组件中必须存在一个。而在 NoneOf 的情况下,我们不希望列出的组件存在。NoneOf 不是独立的描述,这意味着您将无法编写 context.GetGroup(GameMatcher.NoneOf(GameMatcher.Position));。这是被禁止的,因为它会创建一个非常大的集合。NoneOf 只能与 AllOfAnyOf 结合使用。

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

通过这种方式,我们可以说我们需要一个具有 PositionVelocity 组件但不具有 NotMovable 组件的实体组。

AllOfAnyOf 也可以组合使用:context.GetGroup(Matcher.AllOf(Matcher.A, Matcher.B).AnyOf(Matcher.C, Matcher.D).NoneOf(Matcher.E))

匹配器的定义也可以以 AnyOf 开头:context.GetGroup(Matcher.AnyOf(Matcher.C, Matcher.D).NoneOf(Matcher.E))

组观察

如前所述,组始终保持最新状态,因此如果我们可以观察组并在实体被添加或从中删除时得到通知,那么它将提供巨大的好处。更重要的是要理解,当我们在实体上替换一个组件时,旧的组件将被删除,新的组件将被添加。这意味着实体将离开一个组,然后以新值重新进入该组。这为我们提供了反应式编程的基础。

在 Entitas-CSharp 中,在内部我们实际上并没有删除和添加组件。生成的代码会询问用户获取新值,像是我们会删除具有旧值的组件一样触发事件,然后在组件中设置新值,再像是添加了新组件一样触发事件。通过这种方式,我们避免了内存分配,并模拟了使用不可变组件的感觉。

组有以下事件,您可以订阅它们:

  • OnEntityAdded
  • OnEntityRemoved
  • OnEntityUpdated

其他类似 Collector、Index 和 Reactive 系统的组件也使用了相同的事件。因此,对于日常工作,您可能可以使用这些事件。但如果您想构建一些自定义内容,您可能需要查看实现细节。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值