为啥我的 SpriteKit update() 函数会创建多个 NSTimers?
Posted
技术标签:
【中文标题】为啥我的 SpriteKit update() 函数会创建多个 NSTimers?【英文标题】:Why is my SpriteKit update() function creating multiple NSTimers?为什么我的 SpriteKit update() 函数会创建多个 NSTimers? 【发布时间】:2016-02-28 05:04:59 【问题描述】:我正在创建一个 SpriteKit 游戏,它会根据经过的时间进行更新。游戏使用NSTimer
及其scheduledTimerWithTimeInterval
方法生成敌人,每2.0 秒调用一次spawnEnemy
函数。
当 5 秒过去后,应该有一个非常短暂的中场休息,防止新敌人生成以显示关卡变化动画。
当到达最初的 5 秒时,一切正常,直到条件 self.nextLevelDelayTicker == 100
。一旦满足此条件,"YOLO"
字符串只会在控制台中触发一次。但是,我假设NSTimer
的多个实例被创建并存储在self.timer
中,因为在调用self.resumeGame()
以创建新的预定计时器后会产生大量敌人。
关于为什么会发生这种情况的任何想法,即使我在条件中设置了标志,只调用一次 self.resumeGame()
函数?
func resumeGame()
// Start game timer
// Need a way to access ib action of pause button
self.timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: "spawnEnemy", userInfo: nil, repeats: true)
override func update(currentTime: CFTimeInterval)
/* Called before each frame is rendered */
if gameTicker.isActive == true
gameTicker.increment()
// If gameTicker is equal to 5 seconds, increase enemy amount
if gameTicker.getTimePassed() % 500 == 0
self.enemyAmount += 1
self.timer?.invalidate()
levelCount += 1
gameTicker.isActive = false
// If level has been completed and last ghost has been killed, activate next level scene
if gameTicker.isActive == false && enemyArray.count == 0
self.nextLevelDelayTicker.increment()
if self.nextLevelDelayTicker.getTimePassed() == 100
print("YOLO")
self.gameTicker.isActive = true
self.nextLevelDelayTicker.reset()
self.resumeGame()
【问题讨论】:
下面的答案值得考虑,但就您的问题而言,您创建了计时器变量并放置在更新中。每次调用 update 时都会创建一个新的计时器,因此尽管下面的答案很好,但我喜欢使用 skaction 并在那里创建我的计时器并在适当的变量中而不是在 update 方法中调用它们。但这只是我。???? 【参考方案1】:尝试遵循您的代码.. 但我认为您在这里的方法对于 spritekit 来说不是很好。它可能使事情变得比它需要的复杂得多。
您可以直接使用更新方法来跟踪时间。重写这部分代码可能值得。在 spritekit 中会更好地工作,并且不太容易出现错误。
您真正需要的只是增量时间。
场景属性
// time values
var delta = NSTimeInterval(0)
var last_update_time = NSTimeInterval(0)
// some time youre trying to keep track of
var timeLimit = NSTimeInterval(5)
var timeLimitMax = NSTimeInterval(5)
场景的更新方法
func update(currentTime: NSTimeInterval)
if last_update_time == 0.0
delta = 0
else
delta = currentTime - last_update_time
last_update_date = currentTime
// now we can keep track of time
timeLimit -= self.delta
if timeLimit <= 0
// do something and reset timer
timeLimit = timeLimitMax
现在,如果您要持续每隔几秒生成一些东西,那么我们甚至不需要打扰 update
来执行此操作。只需将其放入您的viewDidLoad
现在我们将永远每两秒运行一次此代码。最好的部分是这将自动暂停和恢复您的游戏。您不必过多地管理 SKAction。 spritekit 为你做的:)
let spawnAction = SKAction.repeatActionForever(
SKAction.sequence([
SKAction.waitForDuration(2),
SKAction.runBlock(
[unowned self] in
self.spawnEnemy()
)
])
)
runAction(spawnAction)
【讨论】:
我赞成你的回答,因为这是 SpriteKit 的做法,但你应该稍微改变 spawnAction。首先,您需要在块内显式地使用 self 才能进行编译。其次,它将创建强引用循环,并且在过渡到下一个场景后,场景永远不会被释放,因为自我被捕获并且动作是无止境的。所以在过渡之前,要么显式删除动作,要么在块内使用捕获列表(无主的自我)将解决问题。 好点..我在没有 xcode 的情况下编写了这段代码,所以我确定它不是 100% 完美的。我会编辑。 关于基于计时器生成敌人的非常好的答案。我摆脱了我所有的NSTimer
s,并用一个 SKAction 取而代之。暂停/恢复功能现在就像一个魅力。不过有一件事,我需要能够每 15 秒暂停一次spawnAction
SKAction 5 秒,以显示动画并防止敌人在此期间生成。一旦 5 秒延迟结束,我需要能够重新激活 SKAction
。是否有可用的暂停SKAction
方法?
我是否只需将大约 7 个 SKAction.waitForDuraction(2)
s 硬编码到 SKAction.repeatActionForever
中,然后在最后添加一个 SKAction.waitForDuraction(5)
?需要注意的是,只有在所有敌人都被杀死/从场景中移除后,才能激活 5 秒的动画延迟。
我读了你写的几遍,并没有真正理解你想要做什么。但是,一旦它变得像这样复杂,我倾向于开始使用 update 和 ditch skaction。当你做一次性的事情时,Skaction 很棒。但是一旦设置好,你就不能修改它。您只能取消它并制作一个新的。如果涉及到逻辑和不断变化的条件,那么此时最好使用更新以上是关于为啥我的 SpriteKit update() 函数会创建多个 NSTimers?的主要内容,如果未能解决你的问题,请参考以下文章
SpriteKit - 为啥我的游戏会随着新 iOS 版本的发布而出现错误?
为啥我的声音让我的游戏在 Swift Spritekit 中滞后?