【问题标题】:Should a GKEntity have properties or methods to access a component's features?GKEntity 是否应该具有访问组件功能的属性或方法?
【发布时间】:2017-01-15 14:57:53
【问题描述】:

我正在尝试围绕游戏实体系统并使用 GamePlayKit。 我在以下情况下苦苦挣扎:

  • RenderComponent 是一个 GKComponent 引用 SKSpriteNode 以显示我的实体。
  • MetaDataComponent 是另一个组件,它包含有关实体的各种信息(在我的例子中,这将包含 MapXMapY、...等属性)

我有一个源自GKEntityCharacterEntity

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

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

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

我的想法:

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

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

【问题讨论】:

  • 很好的问题。这是 Apple 游戏 WIP 中“被遗忘”的框架,就像 CAKeyFrameAnimation 是 Apple 平台上被遗忘的动画方式一样。

标签: sprite-kit gameplay-kit


【解决方案1】:

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

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

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

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

articlesupporting code 对我理解 ECS 有很大帮助。 DemoBots example 是另一个面向 spriteKit 的实现。

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

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

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

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

【讨论】:

  • 查看 Apple 的演示,我看到了组件中的功能,他们使用系统以特定顺序更新组件。对我来说,这意味着,他们的方法不是传统的或“纯粹”的方式。你会同意吗?以您对 ECS 的了解,您还介意看看gamedev.stackexchange.com/questions/135259/… 吗?
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 2020-10-28
    相关资源
    最近更新 更多