我曾经使用过Sprite Kit并使用update方法来设置每个时间步骤需要处理的内容。但是现在我想学习SceneKit和Swift,并且似乎找不到相应的方法。
你能否为我提供一个实现SceneKit update方法的例子?谢谢。
(是的,我知道这个问题是关于 SceneKit 而不是 SpriteKit,但它涉及到两个框架之间的共性和差异,所以在这个答案中我会涉及这些内容。)
在 SpriteKit 中,游戏循环方法(update
、didSimulatePhysics
等)最初是属于场景类 SKScene
的一部分。不过这并不总是最好的选择,你可能更想把场景实例当作数据而非实现游戏逻辑的地方(尤其是现在可以在 Xcode 6 的图形场景编辑器中完全构建场景了)。因此,在 iOS 8 和 OS X Yosemite 中,这些方法被放在了两个地方。如果你已经为每帧的游戏逻辑创建了 SKScene
子类,那么你可以继续使用它们。但是,如果你希望把代码放在其他地方,你可以在场景上设置一个代理,并在代理中实现对应的 SKSceneDelegate
方法。
SceneKit 更注重职责分离。一个 SCNScene
更接近于一个纯数据模型对象,而所有渲染循环功能都由用于显示场景的视图(或其他对象)管理。通常你会在一个 SCNView
中显示一个场景 —— 但也有其他类可以渲染场景,所以它们的公共 API 可在 SCNSceneRenderer
协议中找到。使用该协议定义的 delegate
属性来为你的视图设置代理,在代理中实现 SCNSceneRendererDelegate
方法,参与渲染循环的关键阶段。
SceneKit 的循环阶段几乎直接对应 SpriteKit 的循环阶段:update:
变成了 renderer:updateAtTime:
,didEvaluateActions:
变成了 renderer:didApplyAnimationsAtTime:
(因为它包括 Core Animation 风格的动画和 SpriteKit 风格的操作),等等。
因此,要在 SceneKit 中实现与 SpriteKit 中每帧的 update
方法相当的功能,请按照以下步骤操作:
将你的自定义对象(比如一个视图控制器)设置为你的 SCNView
实例的 delegate
。
在这个自定义类中,实现下面的方法:
func renderer(_ aRenderer: SCNSceneRenderer!, updateAtTime time: NSTimeInterval) {
// per-frame code here
}
或者对于其他SCNSceneRendererDelegate
方法执行类似的操作,以便在处理操作或物理效果后执行每帧逻辑。