You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Timer未触发问题:重复调用loadPatternEnemies无法生成敌人

问题排查与修复方案

嘿,我来帮你拆解这个问题!从你描述的现象——第二次调用loadPatternEnemies(number: 0)能打印in here?却没生成敌人——来看,问题大概率出在你使用的Timer.scheduledTimer相关逻辑上,下面是几个最常见的诱因和对应的解决思路:

1. 旧Timer未清理导致逻辑冲突

如果第一次调用时创建的parentTimer没有被失效(invalidate),第二次调用又新建了一个Timer,很可能会导致两个Timer的逻辑互相干扰,或者旧Timer占用了资源,让新Timer的敌人生成逻辑无法正常执行。而且如果parentTimer是函数内的局部变量,第一次调用结束后它会被销毁,但Timer.scheduledTimer会被RunLoop持有,重复创建多个Timer只会让情况更混乱。

修复方案:
把parentTimer改成类的属性(别放在函数里当局部变量),这样每次调用loadPatternEnemies前,先检查并清理旧Timer,再创建新的:

class YourGameClass {
    // 把Timer定义为类属性,方便管理
    var parentTimer: Timer?
    
    func loadPatternEnemies(number: Int) {
        switch number {
        case 0:
            print("in here?")
            // 先干掉旧Timer,避免冲突
            parentTimer?.invalidate()
            // 创建新Timer,记得用弱引用捕获self
            parentTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in
                // 这里写你的敌人生成逻辑
                // 等这波敌人全生成/击败后,记得调用timer.invalidate()销毁Timer
            }
        // 处理其他case...
        }
    }
}

2. Timer的RunLoop模式不匹配

如果你的游戏是基于SpriteKit,或者在UIKit的特殊场景下运行(比如用户正在滑动屏幕),直接用Timer.scheduledTimer可能会让Timer“罢工”——因为默认的scheduledTimer会被加到RunLoop的default模式下,而当RunLoop处于UITrackingRunLoopMode(比如处理触摸滑动)时,default模式的Timer会暂停。

修复方案:
手动把Timer加到RunLoop的common模式下,确保它在各种场景都能正常触发:

parentTimer = Timer(timeInterval: 1.0, repeats: true) { [weak self] timer in
    // 敌人生成逻辑
}
// 添加到common模式,保证不会被UI操作打断
RunLoop.current.add(parentTimer!, forMode: .common)

另外提一句:如果是SpriteKit游戏,更推荐用SKAction.wait(forDuration:)或者SKScene的update(_:)方法来处理定时逻辑,因为SpriteKit有自己的游戏循环,Timer很容易和它不同步。

3. 敌人生成的容器节点状态异常

虽然你能打印日志,但敌人生成的父节点可能已经被移除、隐藏,或者游戏状态已经切换到非战斗模式了,导致生成的敌人根本没法显示出来。

排查&修复:
在敌人生成的代码里加几行日志,确认父节点的状态:

// 假设你把敌人加到gameScene这个节点上
print("父节点是否隐藏:\(gameScene.isHidden)")
print("父节点是否在场景树中:\(gameScene.parent != nil)")

同时检查敌人生成的坐标、zPosition等属性,别把敌人生成到屏幕外面或者被其他节点挡住了。

4. 循环引用导致Timer失效

如果你的Timer闭包没有用[weak self]捕获self,会形成循环引用:self持有Timer,Timer的闭包又持有self,导致第一次的Timer和self都没法被释放,第二次调用的Timer自然也没法正常工作。

修复方案:
闭包里一定要用弱引用捕获self,还可以加个guard判断self是否存在,避免野指针:

parentTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in
    // 先确认self还存在,否则销毁Timer
    guard let self = self else {
        timer.invalidate()
        return
    }
    // 这里写敌人生成逻辑
}

内容的提问来源于stack exchange,提问作者R Bradshaw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:51:18