本記事では、RealityKitを使用して3Dモデルに複数のアニメーションを再生する方法を紹介します。
(※技適特例届け出済み)
デモ
方法
複数のアニメーションを再生させる方法は、以下のように述べられています
The first way is to have one USD file per clip. We can load each USD as an entity and get its animations as AnimationResources. The AnimationResource can then be played on any entity, as long as the names of the joints in its skeleton match the animation.
これは、各アニメーションクリップを個別のUSDファイルとして用意し、それぞれをエンティティとしてロードし、そのアニメーションをAnimationResourceとして取得する方法です。AnimationResourceは、スケルトンのジョイント名が一致する限り、任意のエンティティで再生できます。
引用: Dive into RealityKit 2 - WWDC2021
この方法に従い、以下のステップで実装を進めます。
実装手順
1. USDファイルの準備
各アニメーションクリップを個別のUSDファイルに保存します。アニメーションを適用させたUSDファイルを準備する方法はこちらの記事に記載しています。
2. アニメーションリソースのロード
クリップごとにUSDファイルをロードし、エンティティとして取得します。
3. AnimationResourceの作成
エンティティのアニメーションをAnimationResourceとして取得します。
4. アニメーションの再生
必要なエンティティに対して、取得したAnimationResourceを設定し、再生します。
コード例
struct ImmersiveView: View {
@State var animationResource: [AnimationResource] = []
@State var death = try! Entity.loadModel(named: "death")
var body: some View {
RealityView { content in
do {
if let entity = try? await ModelEntity(named: "scream") {
entity.collision = await CollisionComponent(shapes: [try ShapeResource.generateConvex(from: entity.model!.mesh)])
entity.components.set(InputTargetComponent())
entity.playAnimation(entity.availableAnimations[0].repeat())
content.add(entity)
}
} catch {
print("Error loading model or setting up entity: \(error)")
}
}
.onAppear {
animationResource.append(death.availableAnimations[0])
}
.gesture(tapGesture)
}
private var tapGesture: some Gesture {
TapGesture()
.targetedToAnyEntity()
.onEnded { value in
value.entity.playAnimation(animationResource[0], transitionDuration: 0.05)
}
}
}
上記のコードでは、タップジェスチャーが検出されたときに、ModelEntityに対して指定されたAnimationResourceを再生します。
応用
Vision Proの位置に応じて3Dモデルを自分の方向に移動させ、イベントが発生したタイミングでさまざまなアニメーションを再生することで、よりゲームっぽくなります。
参考資料