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

如何正确移除已移出场景的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 03:15:05