Unreal Engine 勉強会 ~レイキャストの実装例について~


こんにちは。ゲーム事業部(東京)のエンジニアの笠松です。

今回はアドグローブのゲーム事業部内で定期的に開催しているUnreal Engine(以後、UE)勉強会について、自分が発表した内容をご紹介します。


目次


はじめに

「UE勉強会って何?」「どんなことをやっているの?」などの紹介については、以下の記事をご参照ください。
blog.adglobe.co.jp

普段自分がUE勉強会で発表している内容は、以下の通りです。

  • 実際に案件で使用している機能について、学んだことや躓いたこと、工夫したことなどをまとめる
    • 案件では、主人公周りの実装を主に担当しています
  • BluePrintのノードやC++のコードでの説明よりも、考え方や思考の流れなどを主に伝えるようにする
    • 考え方を知っていれば、別の箇所でも流用できることがあるため考え方を重視しています

その中で、今回はレイキャストの実装例として、以下の2つをご紹介します。

  • 登れる壁の判定
  • ツタ移動における移動可否の判定

なお、記事中のUEのバージョンは、5.0.2になります。


UEにおけるレイキャスト

まずUEにおけるレイキャストについては、以下の公式ドキュメントをご参照下さい。
docs.unrealengine.com

またUE自体のデバッグ表示に加えて、資料としてより分かりやすくなるように追加でデバッグ表示を行い、以下のようにしています。

デバッグ表示の説明


登れる壁の判定

実装例

黄色のアウトライン表示が登ろうとしている壁(画像右)
上記のような壁に対して、以下のようなフローで実装しています。

  1. 足元(最低の登れる壁の高さより少し低い高さ)から、進行方向に向かって、壁検知距離までライントレース
    1. 相対している壁の情報を取得
      • 取得した情報(位置や法線)を元に、登れる壁なのか判定
  2. 上記の情報を元に上方から下方に向かってライントレース
    1. 登ろうとしている壁の上部の情報を取得
      • 法線や操作キャラの位置を元に壁の高さなど算出し、登れる壁なのか判定
        (壁の上部が角度がつきすぎだったり、壁が高すぎたりする場合、登れない壁と判定するなど)

上記で取得したトレース情報は、登れる壁なのかどうかの判定処理だけでなく、実際にモーションを再生して壁を登るさいの調整用の値としても利用可能です。
(壁の位置に合うように操作キャラの位置や角度を調整したり、高さに応じてモーションを切り替えたりなど。)

実際に実装すると以下のようになります。

登れる壁の判定の実装例
(壁を登るモーションは用意していないので、急に移動していますが気にしないで下さい)


発生した問題と原因

テスト中は問題ありませんでしたが、本番のAssetにて壁に登れない問題が多発しました。

何故か登れない壁

各ステップでログを仕込んで、確認したところ 登ろうとしている壁の上部の法線(角度) が想定外な値になっており、トレースの状況をワイヤーフレームで見てみると、微妙に斜めになっている部分にヒットしているのがわかりました。
結果、壁の上部が登れない角度として判定されてしまい、壁に登れない状態になってしまっていました。

ワイヤーフレームでのトレースの状況


実装例(改修Ver.)

一部の斜めになっているCollisionを超えて、平らな面を取得する方法を色々と検討しました。

Collision自体をどうにかできないか…

  • そもそも何故Collisionの一部が斜めになっているのか?
    • モデルをUEにインポートした際に自動的に作成されている
  • Collisionを調整するか、壁登り判定用にCollisionを作成する?
    • コードはそのまま使えるが、モデル1つずつ調整するのはコスト的に現実的ではない
      • やはり、実装を工夫して平らな面を取得するしかなさそう…

実装の工夫方法…

  • 相対している壁の位置から一定距離ずらすか?
    • モデルによって、斜めになっている幅が違うため、一定の値でやるのは不適切
  • 問題となっているのは、斜めになっている一部だけなので、ライントレースをずらしていけば、取得したい上部の情報が取得できるはず…!
    • 複数回ライントレースを行い、前回トレース結果と法線が一致する面(連続した平面)を取得すれば出来そう

というわけで、以下のように実装を変更しました。(赤文字が変更箇所です

  1. 足元(最低の登れる壁の高さより少し低い高さ)から、進行方向に向かって、壁検知距離までライントレース
    1. 相対している壁の情報を取得
      • 取得した情報(位置や法線)を元に、登れる壁なのか判定
  2. 上記の情報を元に上方から下方に向かって以下の様にライントレース
    1. 進行方向に少しずつずらしながら、複数回ライントレースを行い、連続した平面 を登ろうとしている壁の上部の情報として取得
      • 法線や操作キャラの位置を元に壁の高さなど算出し、登れる壁なのか判定
        (壁の上部が角度がつきすぎだったり、壁が高すぎたりする場合、登れない壁と判定するなど)

上記を実装すると以下のようになり、無事本番Assetでも登れるようになりました。

登れる壁の判定の実装例(改修Ver.)


ツタ移動における移動可否の判定

黄色のアウトライン表示がツタ

ツタ移動の移動可否の判定要素として以下が定義されており、全て移動可能と判定されないと移動はできない仕様となっています。

  • 移動先にツタがある場合、移動可能
  • 移動先に障害物がある場合、移動不可能

ただし、移動先の判定として入力値そのもので判定するのに加えて、上下と左右で分けての判定も行います。
これは、正しい入力でないと移動できないとすると操作のストレスに繋がってしまうため、このようにしています。
(例えば、斜め左上にコントローラー入力した際に、左方向には移動可能だが上方向には移動不可の場合、入力値分の移動量だけ左方向にのみ移動する。)

各移動可否の判定要素は以下のようなフローで実装しています。


移動先にツタがあるかどうかの実装例

  1. 入力に応じて、ライントレースを実施する手足を決定
    1. 入力方向とは逆の位置はライントレース不要とする
      • 例えば、左上に移動しようとしている場合、右足の移動先のチェックは行わない
  2. 対象の手足の位置から以下の通りライントレース
    1. 移動量(上下左右合わせ)を加味して、Actorの向いている方向にライントレース
      • ヒットした場合、その位置は移動可能として次の対象の手足の位置でのライントレースに移行する
    2. 移動量(上下のみ)を加味して、Actorの向いている方向にライントレース
      • ヒットした場合、その位置は縦移動可能とする
    3. 移動量(左右のみ)を加味して、Actorの向いている方向にライントレース
      • ヒットした場合、その位置は横移動可能とする
    4. 縦にも横にも移動できない場合、移動不可として、以降のライントレースを中止


移動先に障害物があるかどうかの実装例

  1. 入力に応じて、起点となる位置とライントレース先となる手足とを決定
    1. 入力方向とは逆の位置はライントレース不要とする
      • 例えば、左上に移動しようとしている場合、右足の移動先のチェックは行わない
    2. 手足の位置の間を求める必要があるため、ライントレースの起点となる位置を決定する
      • 例えば、左上に移動しようとしている場合、左手の位置が起点となる
  2. 起点となる位置から以下の通りライントレース
    1. 移動量(上下左右合わせ)を加味して、ライントレース先となる手足に向かってライントレース
      • ヒットしなかった場合、その位置は移動可能として次のライントレース先となる手足でのライントレースに移行する
    2. 移動量(上下のみ)を加味して、ライントレース先となる手足に向かってライントレース
      • ヒットしなかった場合、その位置は縦移動可能とする
    3. 移動量(左右のみ)を加味して、ライントレース先となる手足に向かってライントレース
      • ヒットしなかった場合、その位置は横移動可能とする
    4. 縦にも横にも移動できない場合、移動不可として、以降のライントレースを中止

上記を実装すると以下のようになり、ツタがない部分や障害物に当たる箇所でこすりつけるようにしながらの移動ができるようになりました。

ツタ移動における移動可否の判定の実装例


さいごに

以上、UE勉強会で発表したレイキャストの実装例を紹介しました。
実際の案件では、この他にもさまざまな操作に応じてレイキャストで必要な情報を取得しています。
また、本記事の内容以外にもUEで便利なComponentの説明や拡張Sampleだったり、UEにおけるIKの実装だったりなど発表しておりますので、またの機会にそれらもご紹介できればなと考えています。

最後まで読んでいただき、ありがとうございました。




現在アドグローブではゲームエンジニアを含め、さまざまなポジションで一緒に働く仲間を募集しています。
詳細については下記からご確認ください。みなさまからのご応募お待ちしております。

hrmos.co