GKEntity 是否应该具有访问组件功能的属性或方法?
Should a GKEntity have properties or methods to access a component's features?
我正在尝试全神贯注于游戏实体系统并使用 GamePlayKit。
我正在努力应对以下情况:
RenderComponent
是一个 GKComponent
,它引用了一个 SKSpriteNode
来显示我的实体。
MetaDataComponent
是另一个包含有关实体的各种信息的组件(在我的例子中,这将包含 MapX
、MapY
、...等属性)
我有一个 CharacterEntity
派生自 GKEntity
.
为了初始化我的实体,我传递了用于精灵的纹理名称。这允许我创建 RenderComponent
.
要初始化 MetaDataComponent
我有三个选项,我想知道其中一个是否被认为是最佳实践(而且,哪个是最差的实践)?
- 对于我的组件中的每个 属性,向
init()
添加一个参数
- 在
Character
class 中公开属性,这将更新组件的属性。
- 将模型对象传递到我的实体并从中初始化组件。
我的想法:
- 第 1 条:我的实体拥有的组件越多,我获得的参数就越多...这不是我的偏好。
- 数字 2:一个实体应该是 "stupid" 并且不携带任何数据。在最纯粹的形式中,一个实体只是一个数字。里面加道具"feels"错了
- 数字 3:对我来说,拥有一个像
MetaData
这样的模型对象感觉最好但也是多余的,因为数据然后在模型对象的组件 和 中。也许让组件存储模型对象而不是它的属性?
再举一个例子:如果我希望一个实体有一个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
}
我正在尝试全神贯注于游戏实体系统并使用 GamePlayKit。 我正在努力应对以下情况:
RenderComponent
是一个GKComponent
,它引用了一个SKSpriteNode
来显示我的实体。MetaDataComponent
是另一个包含有关实体的各种信息的组件(在我的例子中,这将包含MapX
、MapY
、...等属性)
我有一个 CharacterEntity
派生自 GKEntity
.
为了初始化我的实体,我传递了用于精灵的纹理名称。这允许我创建 RenderComponent
.
要初始化 MetaDataComponent
我有三个选项,我想知道其中一个是否被认为是最佳实践(而且,哪个是最差的实践)?
- 对于我的组件中的每个 属性,向
init()
添加一个参数
- 在
Character
class 中公开属性,这将更新组件的属性。 - 将模型对象传递到我的实体并从中初始化组件。
我的想法:
- 第 1 条:我的实体拥有的组件越多,我获得的参数就越多...这不是我的偏好。
- 数字 2:一个实体应该是 "stupid" 并且不携带任何数据。在最纯粹的形式中,一个实体只是一个数字。里面加道具"feels"错了
- 数字 3:对我来说,拥有一个像
MetaData
这样的模型对象感觉最好但也是多余的,因为数据然后在模型对象的组件 和 中。也许让组件存储模型对象而不是它的属性?
再举一个例子:如果我希望一个实体有一个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
}