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

如何获取并控制通过SCNScene加载到SCNView的USDZ模型自带动画?

这个问题我之前处理过不少次——USDZ模型的动画经常藏在你没注意的地方,不是直接挂在节点的animationKeys里的。让我一步步帮你解决:

第一步:改用SCNSceneSource加载,禁用自动播放

你直接用SCNScene(url:)加载模型时,场景默认会自动播放自带的动画,而且这些动画可能并没有直接附加到节点上,而是存在于SCNSceneSource的资源容器里,这就是为什么你遍历所有节点都找不到animationKeys的原因。

先换一种加载方式,用SCNSceneSource来获取所有资源,同时关闭自动播放的默认行为:

guard let sceneSource = SCNSceneSource(url: url, options: [
    SCNSceneSource.LoadingOption.checkConsistency: true,
    // 关键配置:阻止场景自动播放所有内置动画
    SCNSceneSource.LoadingOption.playAutomatically: false
]) else {
    fatalError("Failed to load scene source from URL")
}

// 从sceneSource中加载场景实例
guard let scene = sceneSource.scene() else {
    fatalError("Failed to retrieve scene from source")
}

sceneView.scene = scene
sceneView.scene?.isPaused = true

第二步:获取模型自带的所有动画

通过sceneSource的animationIdentifiers属性,你能拿到所有内置动画的唯一标识:

let animationIDs = sceneSource.animationIdentifiers
print("Found \(animationIDs.count) animations: \(animationIDs)")

这些ID就是你后续控制动画的核心依据。

第三步:绑定动画到节点并控制播放

接下来,你可以通过ID获取对应的SCNAnimationPlayer(这是控制动画播放/暂停/停止的核心对象),然后把它绑定到目标节点上——如果模型的动画有指定目标节点,你可以通过节点名称精准查找;如果不确定,绑定到根节点也能生效:

for animationID in animationIDs {
    // 获取对应动画的播放器
    guard let animationPlayer = sceneSource.player(forAnimationIdentifier: animationID) else {
        print("Failed to load player for animation \(animationID)")
        continue
    }
    
    // 示例:绑定到根节点,你可以替换成具体子节点的名称
    let targetNode = scene.rootNode
    // 将播放器绑定到节点,用动画ID作为key
    targetNode.addAnimationPlayer(animationPlayer, forKey: animationID)
    
    // 现在你可以直接控制这个播放器:
    // animationPlayer.play()    // 启动播放
    // animationPlayer.pause()   // 暂停动画
    // animationPlayer.stop()    // 停止并重置动画
}

第四步:后续随时控制动画

之后如果需要调整某个动画状态,只需要通过节点和对应的key获取播放器即可:

// 暂停指定动画
if let player = scene.rootNode.animationPlayer(forKey: "YourAnimationID") {
    player.pause()
}

// 重新启动播放
player.play()

// 彻底移除动画(停止+清除资源)
scene.rootNode.removeAnimation(forKey: "YourAnimationID")

为什么之前找不到动画?

USDZ格式的动画通常是作为独立资源存储在场景源中的,而不是直接附加到节点上。直接用SCNScene(url:)加载时,系统会自动帮你把动画绑定到节点并播放,但不会把这些动画的key暴露在节点的animationKeys里——只有当你手动添加动画播放器时,animationKeys才会显示对应的key。

这样处理后,你就能完全掌控模型的所有动画了,再也不会出现不受控制的自动循环了。

内容的提问来源于stack exchange,提问作者Praveen Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 01:34:09