Sprite Kit实现步计数器时循环SKAction时长无法动态更新问题
问题根因
SKAction 实例创建完成后所有入参会被固化,使用repeatForever包裹固定等待时长的action序列时,循环执行的是首次生成的action实例,不会在每轮循环时重新调用间隔计算函数读取最新值,因此间隔时长会一直停留在首次创建时读取的初始值,无法动态更新。
可直接落地的实现方案
放弃固定间隔action套永久循环的写法,改用递归调度逻辑:每次计步逻辑执行完成后,动态计算下一次的等待间隔,再生成新的等待action触发下一轮计步,即可实现间隔随规则动态变化的效果。
- 先在
SKScene子类中定义三个状态属性:- 计步器数值,初始值为0
- 当前计步间隔时长,初始值1.0秒
- 累计运行时长,初始值0.0,用于判断是否达到提速阈值
- 封装递归计步方法,每轮执行时使用最新的间隔值创建等待action,计步完成后校验是否需要提速,再调度下一轮执行
import SpriteKit class GameScene: SKScene { // 计步器状态 private var stepCount = 0 private var currentStepInterval: TimeInterval = 1.0 private var totalElapsed: TimeInterval = 0.0 // 规则常量 private let speedUpDivisor = 1.1 private let speedUpInterval: TimeInterval = 5.0 // 启动计步器 func startStepCounter() { // 重置状态 stepCount = 0 currentStepInterval = 1.0 totalElapsed = 0.0 scheduleNextStep() } // 调度下一次计步 private func scheduleNextStep() { let wait = SKAction.wait(forDuration: currentStepInterval) let tick = SKAction.run { [weak self] in guard let self = self else { return } // 计数值+1 self.stepCount += 1 // 累计时长,判断是否触发提速 self.totalElapsed += self.currentStepInterval if self.totalElapsed >= self.speedUpInterval { self.currentStepInterval /= self.speedUpDivisor // 扣减阈值保留余数,避免时长累计误差 self.totalElapsed -= self.speedUpInterval } // 调度下一轮 self.scheduleNextStep() } run(SKAction.sequence([wait, tick]), withKey: "stepCounterRunning") } // 停止计步器时调用 func stopStepCounter() { removeAction(forKey: "stepCounterRunning") } }
该实现通过action key标记计步任务,启停控制逻辑清晰,每次生成等待action时都会传入最新计算得到的间隔值,完全匹配初始1秒间隔、每累计5秒间隔除以1.1逐步提速的需求,不存在固定action参数不更新的问题。
内容的提问来源于stack exchange,提问作者user18908963
相关产品推荐
相关产品推荐

