如何避免在 SpriteKit 中传递 currentTime?
How to avoid passing currentTime about in SpriteKit?
我在开发我的应用程序时发现我的一些节点需要访问传递给更新方法的 currentTime 以实现业务逻辑。
不断地将其作为参数传递给所有可能需要它的初始化程序和方法似乎很麻烦。
我想知道其他开发人员可能对这个问题有什么解决方案(是否有任何标准模式)。访问系统时间是一个选项,但可能会有一些开销,并且每次调用时都会有所不同。
也许可以使用全局变量,但我想知道是否存在任何线程问题或在闭包中使用它的问题。
选项?
嗯,我想你可以创建某种全局变量,例如:
static var _currentTime: CFTimeInterval = 0
然后在您的更新函数中,您可以将当前时间分配给该变量:
override func update(currentTime: CFTimeInterval) {
_currentTime = currentTime
}
只要您在任何范围之外声明全局变量,您就应该能够从游戏中的任何地方访问它。
我从全局变量方法开始,这是一个显而易见的答案,也是一个赞成的方法。这很简单,但我并不是很满意。最后,我想到了以下看起来更干净的方法。
我 运行 我的所有自定义定时操作现在直接或间接来自 SKAction.runBlock
或 SKAction.customActionWithDuration
.
的操作块 运行
如果我想知道某个特定事件的时间,我会在我的操作列表中插入一个操作,如下所示:
SKAction.customActionWithDuration(level.duration, actionBlock : {(node, elapsedTime) in
self.elapsedTime = elapsedTime
})
如果我需要其他事情与这个计时器同时发生,我只需使用 SKAction.group
到 运行 同时发生所有事情。
唯一的小问题是块引用 self
,我从不喜欢它,因为它依赖于作为节点的动作创建者,但你总是可以投射 node
到实际的节点类型并使用它。
更新:
我发现 SpriteKit 中动作的执行并不是那么可靠,就它们实际开始和结束的时间而言。看起来可能存在一些漂移 - 框架可能会延迟动作的开始,或者漂移可能发生在序列中。在前一种情况下,时钟可能不会像您认为的那样开始滴答作响。对于恒定的参考时间,使用全局变量方法可能会更好。
在我目前正在开发的应用程序中,我实现了以下内容:
protocol Updatable {
func update(currentTime: NSTimeInterval)
}
Updatable
任何你想根据当前时间更新的节点都要实现
然后您需要一个自定义 SKScene
,它将更新任何符合 Updatable
的子节点。对于 Swift 2:
class MyScene: SKScene {
public override func update(currentTime: NSTimeInterval) {
super.update(currentTime)
for case let child as Updateable in children {
child.update(currentTime)
}
}
}
或者,对于 Swift 1,使用:
for child in children {
if let updateableNode = child as? Updateable {
updateableNode.update(currentTime)
}
}
现在已经完成了,您只需要确保您的任何 SKScene
子类都是 MyScene
.
的子类
我在开发我的应用程序时发现我的一些节点需要访问传递给更新方法的 currentTime 以实现业务逻辑。
不断地将其作为参数传递给所有可能需要它的初始化程序和方法似乎很麻烦。
我想知道其他开发人员可能对这个问题有什么解决方案(是否有任何标准模式)。访问系统时间是一个选项,但可能会有一些开销,并且每次调用时都会有所不同。
也许可以使用全局变量,但我想知道是否存在任何线程问题或在闭包中使用它的问题。
选项?
嗯,我想你可以创建某种全局变量,例如:
static var _currentTime: CFTimeInterval = 0
然后在您的更新函数中,您可以将当前时间分配给该变量:
override func update(currentTime: CFTimeInterval) {
_currentTime = currentTime
}
只要您在任何范围之外声明全局变量,您就应该能够从游戏中的任何地方访问它。
我从全局变量方法开始,这是一个显而易见的答案,也是一个赞成的方法。这很简单,但我并不是很满意。最后,我想到了以下看起来更干净的方法。
我 运行 我的所有自定义定时操作现在直接或间接来自 SKAction.runBlock
或 SKAction.customActionWithDuration
.
如果我想知道某个特定事件的时间,我会在我的操作列表中插入一个操作,如下所示:
SKAction.customActionWithDuration(level.duration, actionBlock : {(node, elapsedTime) in
self.elapsedTime = elapsedTime
})
如果我需要其他事情与这个计时器同时发生,我只需使用 SKAction.group
到 运行 同时发生所有事情。
唯一的小问题是块引用 self
,我从不喜欢它,因为它依赖于作为节点的动作创建者,但你总是可以投射 node
到实际的节点类型并使用它。
更新:
我发现 SpriteKit 中动作的执行并不是那么可靠,就它们实际开始和结束的时间而言。看起来可能存在一些漂移 - 框架可能会延迟动作的开始,或者漂移可能发生在序列中。在前一种情况下,时钟可能不会像您认为的那样开始滴答作响。对于恒定的参考时间,使用全局变量方法可能会更好。
在我目前正在开发的应用程序中,我实现了以下内容:
protocol Updatable {
func update(currentTime: NSTimeInterval)
}
Updatable
任何你想根据当前时间更新的节点都要实现
然后您需要一个自定义 SKScene
,它将更新任何符合 Updatable
的子节点。对于 Swift 2:
class MyScene: SKScene {
public override func update(currentTime: NSTimeInterval) {
super.update(currentTime)
for case let child as Updateable in children {
child.update(currentTime)
}
}
}
或者,对于 Swift 1,使用:
for child in children {
if let updateableNode = child as? Updateable {
updateableNode.update(currentTime)
}
}
现在已经完成了,您只需要确保您的任何 SKScene
子类都是 MyScene
.