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

在SceneKit中如何播放USDZ文件中的MDLPackedJointAnimation?

How to Play MDLPackedJointAnimation from a USDZ File in SceneKit

Got it, let's work through getting that MDLPackedJointAnimation playing in your SceneKit scene. The core issue here is that SceneKit doesn't automatically translate animations stored in the MDLAsset's animation collection into SCNAnimationPlayer instances attached to your node—you have to handle that conversion manually. Here's a step-by-step solution:

Step 1: Load the USDZ Asset and Extract the Animation

First, load your asset like you already are, then grab the MDLPackedJointAnimation from the asset's animation pool:

let usdzURL = Bundle.main.url(forResource: "Sitting Laughing", withExtension: "usdz")!
let asset = MDLAsset(url: usdzURL)
asset.loadTextures()

// Fetch your character node from the asset
guard let characterMDLObject = asset.object(at: 0) as? MDLMesh else {
    fatalError("Failed to retrieve the main mesh from the USDZ file")
}
let characterNode = SCNNode(mdlObject: characterMDLObject)

// Pull out the MDLPackedJointAnimation instance
guard let packedAnimation = asset.animations.objects.first as? MDLPackedJointAnimation else {
    fatalError("No MDLPackedJointAnimation found in the asset")
}

Step 2: Bind the Animation to the Character's Skeleton

MDLPackedJointAnimation needs explicit mapping to your character's skeleton joints. We'll create an MDLAnimationBindComponent to link the animation's joint paths to the skeleton's bind transforms:

// Get the skeleton's bind transforms from the SceneKit node
guard let skeletonBindTransforms = characterNode.skeleton?.bindTransforms else {
    fatalError("Character node has no attached skeleton")
}

// Create the bind component and attach it to the MDL mesh object
let bindComponent = MDLAnimationBindComponent(
    jointPaths: packedAnimation.jointPaths,
    jointBindTransforms: skeletonBindTransforms
)
asset.addComponent(bindComponent, to: characterMDLObject)

Step 3: Convert to SCNAnimation and Start Playback

Now convert the metal-focused MDLPackedJointAnimation to a SceneKit-compatible SCNAnimation, create an animation player, attach it to your node, and kick off playback:

// Convert the MDL animation to a SceneKit animation
let scnAnimation = SCNAnimation(mdlAnimation: packedAnimation)

// Configure animation behavior (tweak these to fit your needs)
scnAnimation.usesSceneTimeBase = false // Let the animation run on its own timeline
scnAnimation.repeatCount = .infinity // Loop the animation non-stop
scnAnimation.fadeInDuration = 0.2 // Add a smooth start transition
scnAnimation.fadeOutDuration = 0.2 // Add a smooth end transition if needed

// Create an animation player and attach it to the character node
let animationPlayer = SCNAnimationPlayer(animation: scnAnimation)
characterNode.addAnimationPlayer(animationPlayer, forKey: "SittingLaughing")

// Start the animation
animationPlayer.play()

Key Details to Keep in Mind

  • The MDLAnimationBindComponent is non-negotiable—it bridges the gap between the animation's joint data and your character's skeleton, ensuring the animation applies correctly to each joint.
  • If your USDZ contains multiple animations, loop through asset.animations.objects instead of grabbing the first one, and use unique keys when adding animation players to avoid conflicts.
  • You can control playback later (pause, stop, adjust speed) by fetching the SCNAnimationPlayer instance using the key you assigned.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 17:40:16