我试图围绕游戏实体系统并使用GamePlayKit。 我正在努力解决以下问题:
RenderComponent
是GKComponent
引用SKSpriteNode
来展示我的实体。MetaDataComponent
是另一个包含有关实体的各种信息的组件(在我的情况下,这将包含MapX
,MapY
等属性,...)我的CharacterEntity
来自GKEntity
。
为了初始化我的实体,我传递了用于精灵的纹理名称。这允许我创建RenderComponent
。
初始化MetaDataComponent
我有三个选项,我想知道其中一个被认为是最佳实践(还有哪一个是最差的练习)?
init()
Character
类中公开属性,这将更新组件的属性。我的想法:
MetaData
这样的模型对象感觉最好但也是多余的,因为数据在模型对象的和组件中。也许组件存储模型对象而不是其属性?再举一个例子:如果我希望某个实体拥有RenderComponent
,我可以查询该组件并使用它。或者我可以向实体本身添加一个方法,例如setRenderPosition
,它检查是否存在所需组件并对其进行更新。问题是,这样做是对还是错?
答案 0 :(得分:1)
如果您正在寻找纯Entity Component System
,那么设计包含三个部分:
Entity
:你说的只是一个数字。没别了。
Component
:这只是数据。没别了。
System
:被遗忘的部分。这就是逻辑所在。您可以继承GKComponentSystem<GKComponent>
以在SpriteKit中创建自己的系统。
此article及其supporting code帮助我理解ECS
。 DemoBots 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
}