jeremyjoron
jeremyjoron

Reputation: 93

How to use multiple animations on a USDZ model with RealityKit?

How to use multiple animations for a USDZ 3D character in RealityKit?

Play an idle animation, when it walks, when it jumps, etc.

Upvotes: 1

Views: 2404

Answers (2)

闪电狮
闪电狮

Reputation: 556

My intention is to present multiple animations in the app, so I place the "idle" and "walk" actions in order on the Blender timeline, export them to USDC, and convert them to USDZ through Reality Converter. Then, I use the following code to extract a single AnimationResource from the timeline.

        .onAppear {
            var animationResource: [AnimationResource] = []
            var model3 = try! Entity.loadModel(named: "v3.usdz")
            let definition = model3.availableAnimations[0].definition
            
            //🧍
            let idle = AnimationView(source: definition,
                name: "idle",
                bindTarget: nil,
                blendLayer: 0,
                repeatMode: .autoReverse,
                fillMode: [],
                                     trimStart: 0.0,
                trimEnd: 2.0,
                trimDuration: nil,
                offset: 0,
                delay: 0,
                speed: 1.0)
            
            //🚶
            let walk = AnimationView(source: definition,
                name: "walk",
                bindTarget: nil,
                blendLayer: 0,
                repeatMode: .autoReverse,
                fillMode: [],
                                     trimStart: 2.0,
                                     trimEnd: 10.0,
                trimDuration: nil,
                offset: 0,
                delay: 0,
                speed: 1.0)


            // Create an animation resource from the clip.
            var clipResource = try! AnimationResource.generate(with: idle)
            animationResource.append(clipResource)
        }

Upvotes: 1

Andy Jazz
Andy Jazz

Reputation: 58563

Switch between Multiple Animations in RealityKit

In RealityKit 2023, you can switch between multiple animations like idle, dance or jump, but for that you need the same skeletal structure in each USDZ file. To implement it, you have to put all the animations from several animated USDZ models into AnimationResource collection, and then apply one animation at a time to a character with an identical skeleton. Blending works perfectly here.

You can test my code with Mixamo animations, where each character has an identical skeleton.

I downloaded several animated Mixamo models in .dae format two-three years ago, and after that made a DAE -> SCN -> USDZ conversion using a code published in this post.

enter image description here

import SwiftUI
import RealityKit

struct ContentView : View {

    @State var animationResource: [AnimationResource] = []
    @State var model1 = try! Entity.loadModel(named: "idle.usdz")
    @State var model2 = try! Entity.loadModel(named: "jump.usdz")
    
    var body : some View {
        ZStack {
            ARViewContainer(model: $model1)
                .ignoresSafeArea()
                .onAppear {
                    animationResource.append(model1.availableAnimations[0])
                    animationResource.append(model2.availableAnimations[0])
                }
            VStack {
                Spacer()
                HStack {
                    Spacer()
                    Button("Jump") {
                        model1.playAnimation(animationResource[1].repeat(),
                                             transitionDuration: 0.5)
                    }
                    Spacer()
                    Button("Neutral") {
                        model1.playAnimation(animationResource[0].repeat(),
                                             transitionDuration: 0.5)
                    }
                    Spacer()
                }
            }
        }
    }
}

struct ARViewContainer : UIViewRepresentable {

    @Binding var model: ModelEntity
    let arView = ARView(frame: .zero)
    let anchor = AnchorEntity()

    func makeUIView(context: Context) -> ARView {
        model.scale /= 120
        model.position.y = -0.7
        anchor.addChild(model)
        arView.scene.anchors.append(anchor)
        return arView
    }
    func updateUIView(_ view: ARView, context: Context) { }
}

#Preview {
    ContentView()
}

Upvotes: 3

Related Questions