メインコンテンツへスキップ
  1. 記事/

CharacterのCollisionをMeshの形状に合わせて追加する

UnrealEngine UE5.0 Character

この記事は Unreal Engine (UE) Advent Calendar 2022 の 3 日目の記事です

Character クラスは人型キャラクター用の汎用クラスです

…が、とりあえず動かすのにこれ以上の楽な実装はそうありません
なので人型以外(四足歩行など)で Character クラスを使うときの悩みを解消します

とりあえず、ThirdPersonTemplate の BP_ThirdPersonCharacter の Mesh を四足歩行の動物にしてみましょう
シカとかどうですかね?

シカ

まあこうなります

これをそのまま動かそうとすると、当然こういう悲劇が起こります

当然起こる悲劇

流石にこれは…だめですね

これの対策、正攻法で行くなら以下の 2 択になります

  • SkeletalMesh を少し後ろに下げて、頭と前足を Capsule に入れるようにする
  • Capsule 自体を大きくして、全身が Capsule に入るようにする

前者が一番マトモな方法ですね
ただし尻がはみ出すことは許容しなければなりません

後者もありなのですが、今度は幅が広くなりすぎていい感じにならない…

そこで、AutoWeld の仕組みを使った裏技で、Collsion を追加する方法を提案します

AutoWeld を使った Collision の合成 #

まずは SkeletalMesh をカバーできるように、Collsion を追加してください
追加する際は、Capsule の直下にします
SkeletalMesh の下ではありません

今回はこんな感じにします
もうちょい丁寧な方法は各自でどうぞ…

Collison追加

そして、BeginPlay で、一瞬だけ Capsule の SimulatePhysics を ON にします
Delay Until Next Tick はなくても動きますがまあ念のため

一瞬だけSimulatePhysicsをON

これらの実装をすることで、追加した Collsion が合成され、Collsion をカバーすることができるようになります

貫通しない

どうしてこういう事が起こるのか #

UnrealEngine では、ひとかたまりの Object(RigidBody)は、ひとかたまりで動くように物理シミュレーション空間内に登録する仕組みがあります
これを AutoWeld といいます

Weld…溶接です

この AutoWeld が動作する条件が、物理シミュレーションを ON にしたとき、というわけです

そして AutoWeld は、物理シミュレーションが ON になった Component(PrimitiveComponent)の子供の Collision を再帰的に検索し、まとめて 1 つになるように合成します
Capsule の直下に合成したい Collision を配置した理由がこれです

SkeletalMesh やその子 Component が AutoWeld されない理由について #

SkeletalMesh は PrimitiveComponent ではあるのですが、SkeletalMesh の Collision(PhysicsAsset)は AutoWeld の対象になりません
SkeletalMesh の Collision は、その構造が理由で、PrimitiveComponent の RigidBody の扱いではないからです

SkeletalMesh の Collision、いわゆる Ragdoll は、RigidBody を Constraint で繋ぐ構造になっています
このあたりは PhysicsAsset を見てもらえばわかるかと思います

その構造が、PrimitiveComponent が持つ RigidBody の構造に収まらないため、SkeletalMesh は RigidBody を独自の変数で管理しています
PrimitiveComponent が用意している RigidBody の変数には入りません
なので、処理上 RigidBody はないとみなされ、AutoWeld が起きなくなります

そもそも、Weld してしまうと、物理シミュレーション上で自由に動かせなくなってしまうので、Weld しないようになっている、という理由もあります

SkeletalMeshComponent の子 Component が AutoWeld されない理由は、SkeletalMesh の時点で AutoWeld の再帰処理が途切れてしまうので、それ以下の Collsion は処理が行われないためです
これは SkeletalMesh 以外にも、Collision を持たない SceneComponent を挟んだときにも起こるので、注意しましょう

Weld 周りの処理は C++が読めればわりと簡単に理解できるので、興味がある人は追ってみると良いでしょう

追加:Animation に合わせて動かす #

AutoWeld で合成しましたが、Component としては独立しているので、実はここから Animation(Bone)に合わせて動かすことができます

GetSocketLocation 等で、参照したい Bone の位置を取得し、その位置に Collision を動かせば、Collision の位置を変更できます

Collsionの位置を更新する

これなら複雑に変形するロボット等にも対応できますね

Related

CameraでActorを追尾(Tracking)する方法について
UnrealEngine UE5.0 Cinematic
最後に触ったプロジェクトが自動的に開いてしまう場合
UnrealEngine UE5.0 Troubleshoot
ObjectMixerを使ってLevel上のActorのPropertyを一括編集する
UnrealEngine UE5.1 ObjectMixer LevelDesign Tools