注意
現状ドキュメントが不足、もしくは投稿者が見つけられていないため情報がかなり不正確です。(そのため考えるとしています)
手っ取り早く表題の押し出す壁を実装したい場合は事の発端に貼ってある一番最初のツイートのスレッドを参考にしてください。
環境
Unreal Engine 5.4.2
事の発端
TL上に気になるツイートが流れてきました
CharacterMovementは静止しているとコリジョンが正しく認識しないってUdemyで聞いた。ホントかな?
— TARK🥷 (@LideTark) June 5, 2024
UE5.3で試してみた。
ホントだ。ガタガタだな。 pic.twitter.com/5qjy4bvFTU
実際に試すと動画の通りの動きになりました。
壁にPlayerが押される動きってゲームにあってもおかしくはないものなので驚きました。
原因はCharacterMovementへ実装されている床にめり込まないようにする機能が壁へ反応しているようです。
(多分ソースのResolvePenetrationの部分...?)
また、ツイート主の方がスレッドに乗せている対処法はCharacterMovementComponent内で移動する際に使用している関数をframe毎に呼び出し、CharacterMovement側で衝突判定を行っているものと考えられます。
対処法1
この当行に対して対処法を解説してくださっている方がいました。
ツイートの中では#UE5Study
— 恒吉星光 (@seiko_dev) June 5, 2024
正しさ…の話は一旦置いて、とりあえず何が起きているかを解説してみます。
まず前提として、Blockコリジョン物体をSweep無しで動かすと、Block対象に対しては埋まります(Overlapが発火)。Sweep有りで動かすと接した状態で静止します(Hitイベントが発火)。
では、この押し出し挙動は… https://t.co/sR435rIQMs
- 壁はSweep(つまり障害物があった場合はすり抜けずに止まる)で動かす
- Hit判定が出るように設定しておく
- Hit状態になったら衝突したことによって動けなかった分のベクトル量を求める
- 先ほど求めた分衝突したアクターと壁をOffsetで動かす、壁を動かす際はSweepで動かす
といった処理で疑似的に壁がアクターを押し出しているような動きを実装しています。(多分)
ただしツリー上でもおっしゃられているように条件によって無限ループが発生したりと中々複雑そうです。
実際解説されている実装で壁を動かすとキャラクターが後ろや横から衝突した際に無限ループでエラーになります。
(これを回避するのにHit時の壁のオフセット移動をなくす方法がありますが、キャラクターが壁に向かって動くと壁からキャラクターが離れないため今度は壁が動かなくなります。)
対処法2
これは現状プロジェクトには使えないと思いますがVersion5.4から追加されたMoverプラグインに入っているPhysicsMannyPawnを使用すると壁側に何も細工をしなくとも壁にアクターが埋もれなくなります。
これは新しく追加されたMover2.0によってSimulatePhysicsをONにしないとできなかった挙動が表現できるようになったおかげです。
詳しい解説は以下のalwei氏のブログを参考にしてください(なお5.4.2だとブログ内で紹介されているMoverBasePawnはありません。代わりにPhysicsMannyPawnを継承してクラスを作成すると楽です。MoverBaseに近いのはAnimatedMannyPawnです。)
https://unrealengine.hatenablog.com/entry/2024/03/31/180000
実際に壁で押してみました(右からPhysicsMannyPawn,AnimatedMannyPawn,従来のCharacterMovement)
PhysicsMannyPawnは期待通りの動きをしてくれています。
まとめ
以上TARK氏のツイートとそれに対する反応の流れをまとめたような記事にもなってしまいましたが現状この問題に対しての対処法でした。
正解と呼べるものは小手先では実装できそうにありませんのでこれぐらいにしておきます。
他参考
CharacterMovementについて
Sweepについて