GKEntity 是否应该具有访问组件功能的属性或方法?

Should a GKEntity have properties or methods to access a component's features?

我正在尝试全神贯注于游戏实体系统并使用 GamePlayKit。 我正在努力应对以下情况:

我有一个 CharacterEntity 派生自 GKEntity.

为了初始化我的实体,我传递了用于精灵的纹理名称。这允许我创建 RenderComponent.

要初始化 MetaDataComponent 我有三个选项,我想知道其中一个是否被认为是最佳实践(而且,哪个是最差的实践)?

我的想法:

再举一个例子:如果我希望一个实体有一个RenderComponent,我可以查询那个组件并使用它。或者我可以向实体本身添加一个方法,例如 setRenderPosition 检查所需组件是否存在并更新它。问题又来了,这样做到底是对是错?

如果您正在寻找纯粹的Entity Component System,那么设计由三部分组成:

Entity:正如你所说,只是一个数字。没有别的。

Component:这只是数据。没有别的。

System:遗忘的部分。这就是逻辑所在。您可以继承 GKComponentSystem<GKComponent> 在 SpriteKit 中创建您自己的系统。

这个 article and it's supporting code helped me a lot in understanding ECS. The DemoBots example 是另一个值得关注的面向 spriteKit 的实现。

由于 SpriteKit 有它自己的 ECS 实现和其他怪癖,我相信一些妥协是必要的,例如你需要渲染一个节点,所以如果你想要一个 SpriteComponent,那么你需要将节点嵌入到 SpriteComponet 中或做其他事情 - 我宁愿没有 SpriteComponent,我创建了一个继承自 [=18= 的 VisualEntity ],但我更喜欢关注具有依赖于 update 运行 循环的行为的组件。

回答关于实体属性的问题似乎没有必要,因为您可以在实体中查询您需要访问的任何组件。

guard let spriteComponent = entity?.component(ofType: SpriteComponent.self) else {
   return
}

重要的是要灵活,适应 SpriteKit 并意识到您正在做出的妥协。

要考虑的一个选项是在 GKEntity 上进行扩展。

import SpriteKit
import GameplayKit

extension GKEntity {
    var isSelected: Bool {
        guard let component = self.component(ofType: SelectionComponent.self) else {
            return false
        }

        return component.selectionLocation != nil
    }
}

这使得所有实体都可以使用该功能。

if self.someEntity.isSelected {
    // Handle 
}