GKEntity 和 GKComponent
实体表示游戏的对象,如玩家形象或敌人形象。由于这个物体在没有手臂和腿的情况下做得不多,我们可以为此添加组件。要创建这个系统,apple 有 GKEntity
和 GKComponent
类。
让我们假设我们在以下章节中有以下内容:
class Player: GKEntity{}
class PlayerSpriteComponent: GKComponent {}
GKEntity
实体是组件的集合,并提供若干功能来添加,删除和与组件相互作用。
虽然我们可以使用 GKEntity,但通常会将其子类化为特定类型的游戏实体。
重要的是,只能添加一次类的组件。如果你添加同一个类的第二个组件,它将覆盖 GKEntity
内的第一个现有组件
let otherComponent = PlayerSpriteComponent()
var player = Player()
player.addComponent(PlayerSpriteComponent())
player.addComponent(otherComponent)
print(player.components.count) //will print 1
print(player.components[0] === otherComponent) // will print true
你可能会问为什么。其原因是名为 component(for: T.Type)
的方法,它返回特定类型实体的组件。
let component = player.component(ofType: PlayerSpriteComponent.self)
除了组件方法之外,它还有一个 update
方法,用于将游戏逻辑的增量时间或当前时间委托给它的组件。
var player = Player()
player.addComponent(PlayerSpriteComponent())
player.update(deltaTime: 1.0) // will call the update method of the PlayerSpriteComponent added to it
GKComponent
组件表示实体的某些东西,例如可视组件或逻辑组件。
如果调用实体的更新方法,它将委托给它的所有组件。覆盖此方法用于操作实体。
class PlayerSpriteComponent: GKComponent {
override func update(deltaTime seconds: TimeInterval) {
//move the sprite depending on the update time
}
}
除此之外,还可以覆盖方法 didAddToEntity
和 willRemoveFromEntity
,以通知其他组件有关它的删除或添加。
要操作组件内部的其他组件,可以获得添加组件的 GKEntity。
override func update(deltaTime seconds: TimeInterval) {
let controller = self.entity?.component(ofType: PlayerControlComponent.self)
//call methods on the controller
}
虽然这是可能的,但它不是常见的模式,因为它将两个组件连接在一起。
GKComponentSystem
虽然我们刚刚谈到使用 GKEntity
的更新委托机制来更新 GKComponents
,但是有一种不同的方式来更新 GKComponents
,这被称为 GKComponentSystem
。
如果需要特定类型的所有组件需要一次更新,则使用它。
为特定类型的组件创建 GKComponentSystem
。
let system = GKComponentSystem(componentClass: PlayerSpriteComponent.self)
要添加组件,你可以使用 add 方法:
system.addComponent(PlayerSpriteComponent())
但更常见的方法是将创建的实体与其组件一起传递给 GKComponentSystem
,它将在实体内部找到匹配的组件。
system.addComponent(foundIn: player)
要更新特定类型的所有组件,请调用更新:
system.update(deltaTime: delta)
如果你想使用 GKComponentSystem
而不是基于实体的更新机制,则必须为每个组件提供 GKComponentSystem
并在所有系统上调用更新。