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

SceneKit中暂停USDZ模型动画的问题

SceneKit中暂停USDZ动画的正确方法

直接设置节点的isPaused = true无法暂停USDZ动画,原因是USDZ的动画由SCNAnimationPlayer独立驱动,节点的暂停状态不会影响动画播放器的运行。以下是正确的解决步骤:

问题根源

SCNNode.isPaused仅会暂停节点的渲染、物理模拟等行为,但动画播放器是绑定到节点上的独立执行单元,不受该属性控制。

解决方案

加载USDZ后,需要找到节点关联的所有动画播放器并手动暂停:

1. 修正URL加载逻辑(潜在问题)

原代码中用URL(string: urlfile)加载本地文件会失败,因为string:初始化器适用于网络URL,本地路径应使用URL(fileURLWithPath:)。

2. 遍历并暂停动画播放器

通过节点的animationPlayers字典获取所有动画播放器,逐个暂停;若动画是直接附加在节点上的CAAnimation,也需要暂停对应的动画。

修改后的完整代码:

func loadIdle() {
    guard let urlfile = Bundle.main.path(forResource: "armi_idle", 
                                        ofType: "usdz", 
                                   inDirectory: "Asset.scnassets"),
          let sceneURL = URL(fileURLWithPath: urlfile),
          let scene = try? SCNScene(url: sceneURL)
    else {
        print("加载USDZ资源失败")
        return
    }
    
    guard let findNode = scene.rootNode.childNode(withName: "armi_idle", recursively: true) else {
        print("未找到目标节点")
        return
    }
    
    // 暂停所有关联的动画播放器
    findNode.animationPlayers.forEach { _, player in
        player.isPaused = true
    }
    
    // 额外处理直接附加的CAAnimation(部分USDZ可能用这种方式)
    findNode.removeAllAnimations()

    self.scene.rootNode.addChildNode(findNode)
}

补充说明

如果动画嵌套在子节点中,需要递归遍历所有子节点并暂停其动画播放器:

func pauseAllAnimations(in node: SCNNode) {
    node.animationPlayers.forEach { _, player in
        player.isPaused = true
    }
    node.childNodes.forEach { pauseAllAnimations(in: $0) }
}

// 使用时调用
pauseAllAnimations(in: findNode)

USDZ资产结构示意图

内容的提问来源于stack exchange,提问作者Damiano Miazzi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:54:28