如何正确移除已移出场景的SpriteKit节点 解决箭头节点卡顿不消失问题
故障修复方案
核心问题原因
- 销毁阈值设置不合理:代码中设置的节点销毁阈值是
position.y < -500,但按照你给定的移动距离计算,arrow移动到终点时的y坐标普遍高于-500,永远无法触发销毁逻辑,节点持续堆积占用资源导致卡顿。 - 销毁逻辑执行时机错误:当前销毁检查仅在每次生成新arrow时执行,两次生成间隔5秒,已经移出屏幕的节点无法及时被销毁,进一步加剧了节点堆积问题。
修复方案
推荐使用动作绑定的方式实现自动销毁,无需额外遍历检查,性能开销更低,修复后代码如下:
func startTheArrow() { run(SKAction.repeatForever(SKAction.sequence([SKAction.run(spawnArrow), SKAction.wait(forDuration: 5.0)]))) } func spawnArrow() { let arrow = SKSpriteNode(imageNamed: "arrow") arrow.size = CGSize(width: 50, height: 50) arrow.physicsBody = SKPhysicsBody(rectangleOf: arrow.size) arrow.physicsBody?.affectedByGravity = false arrow.physicsBody?.categoryBitMask = ColliderType.arrow arrow.name = "Arrow" arrow.zPosition = 1 arrow.position = CGPoint(x: frame.size.width * random(min: -0.45, max: 0.45), y: frame.size.height * random(min: 0.6, max: 0.7)) addChild(arrow) // 绑定移动+销毁序列动作,节点移动完成后自动销毁 let moveAction = SKAction.moveBy(x: 0.0, y: -size.height - arrow.size.height, duration: 2) let removeAction = SKAction.removeFromParent() arrow.run(SKAction.sequence([moveAction, removeAction])) }
如果需要保留全局遍历检查的逻辑,可将检查代码放到场景的update方法中每帧执行,同时修改为动态阈值:
override func update(_ currentTime: TimeInterval) { super.update(currentTime) enumerateChildNodes(withName: "Arrow") { node, stop in // 节点完全移出屏幕底部即可销毁,无需写死固定阈值 if node.position.y < -node.frame.height { node.removeFromParent() } } }
内容的提问来源于stack exchange,提问作者user12137285
相关产品推荐
相关产品推荐

