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

如何解决SpriteKit while循环内生成卡牌前添加等待不生效问题

问题根因
  • SKAction.run 是异步非阻塞接口,调用后会立刻返回继续执行后续代码,不会停在当前位置等等待动作执行完。
  • 你写的while循环会在极短时间内跑完所有迭代,所有等待动作几乎同时启动,1秒后所有spawnCard会集中触发,所以会一次性生成所有卡牌。
解决方案

推荐优先使用SpriteKit原生的动作体系实现,和引擎的生命周期适配性更好:
把「等待1秒+生成卡牌+停止条件校验」打包成重复执行的序列动作,满足停止条件时主动终止动作即可,替换你的原有代码如下:

else if standLabel.contains(touch.location(in: self)) {
    // 先移除同标识的旧动作,避免重复触发逻辑冲突
    self.removeAction(forKey: "dealer_auto_spawn")
    
    // 定义单次生成逻辑
    let spawnStep = SKAction.run { [weak self] in
        guard let self = self else { return }
        // 点数达标就终止动作,不再继续生成
        guard self.dealerCardValues.sum() <= 16 else {
            self.removeAction(forKey: "dealer_auto_spawn")
            return
        }
        self.spawnCard()
    }
    
    // 拼接执行序列:先等1秒,再执行生成逻辑
    let sequence = SKAction.sequence([
        SKAction.wait(forDuration: 1),
        spawnStep
    ])
    
    // 循环执行上述序列,直到主动终止
    self.run(SKAction.repeatForever(sequence), withKey: "dealer_auto_spawn")
}

如果你更习惯用GCD实现,也可以用递归延迟调用的方案:

  1. 先在当前类定义独立的生成递归方法:
private func spawnDealerCardLoop() {
    guard dealerCardValues.sum() <= 16 else { return }
    spawnCard()
    // 延迟1秒后触发下一次生成
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
        self?.spawnDealerCardLoop()
    }
}
  1. 在touchesBegan的对应位置直接调用即可:
else if standLabel.contains(touch.location(in: self)) {
    spawnDealerCardLoop()
}

内容的提问来源于stack exchange,提问作者jhon albert

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 02:15:02