如何解决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实现,也可以用递归延迟调用的方案:
- 先在当前类定义独立的生成递归方法:
private func spawnDealerCardLoop() { guard dealerCardValues.sum() <= 16 else { return } spawnCard() // 延迟1秒后触发下一次生成 DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in self?.spawnDealerCardLoop() } }
- 在touchesBegan的对应位置直接调用即可:
else if standLabel.contains(touch.location(in: self)) { spawnDealerCardLoop() }
内容的提问来源于stack exchange,提问作者jhon albert
相关产品推荐
相关产品推荐

