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

时间:2017-01-15 14:57:53

标签: sprite-kit gameplay-kit

我试图围绕游戏实体系统并使用GamePlayKit。 我正在努力解决以下问题:

  • RenderComponentGKComponent引用SKSpriteNode来展示我的实体。
  • MetaDataComponent是另一个包含有关实体的各种信息的组件(在我的情况下,这将包含MapXMapY等属性,...)

我的CharacterEntity来自GKEntity

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

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

  • 对于我的组件中的每个属性,请向init()
  • 添加一个参数
  • Character类中公开属性,这将更新组件的属性。
  • 将模型对象传递给我的实体并从中初始化组件。

我的想法:

  • 数字1:我的实体拥有的组件越多,我得到的参数就越多......这不是我的偏好。
  • 第2号:一个实体应该是"愚蠢的"并没有携带任何数据。在它最纯粹的形式中,实体只是一个数字。在那里添加道具"感觉"错。
  • 编号3:对我来说像MetaData这样的模型对象感觉最好但也是多余的,因为数据在模型对象的组件中。也许组件存储模型对象而不是其属性?

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

2 个答案:

答案 0 :(得分:1)

如果您正在寻找纯Entity Component System,那么设计包含三个部分:

Entity:你说的只是一个数字。没别了。

Component:这只是数据。没别了。

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

article及其supporting code帮助我理解ECSDemoBots example是另一个面向spriteKit的实现。

由于SpriteKit拥有自己ECS的实现以及其他怪癖,我认为必须采取一些妥协措施。你需要渲染一个节点,所以如果你想要一个SpriteComponent,那么你需要将节点嵌入到SpriteComponet中或者做其他事情 - 我更喜欢没有SpriteComponent,我创建了一个继承自{{的VisualEntity 1}},但我更倾向于关注具有依赖于GKEntity运行循环的行为的组件。

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

update

重要的是要灵活,适应SpriteKit并注意你正在做出的妥协。

答案 1 :(得分:0)

要考虑的选项是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 
}