とあるゲームプログラマの挑戦と敗北の歴史

UE4とプログラミングとmayaとpythonとhtmlとマラソンを中心に情報を発信する元「技術ブログを目指すブログ」から再始動した毎日の日々を発信するブログです。

UE4:アンリアルクエスト初級編サンプル解析

5月17日から22日の間、
UE4を利用した学習コンテスト、アンリアルクエストが行われました。

https://www.unrealengine.com/ja/blog/unrealquest-01-archives?sessionInvalidated=true


初級編サンプルが公開されたのでそちらを解析したのをまとめました。

https://epicgames.ent.box.com/s/a6usckg3g8h4mh4nkl811nt78wpdf423



いきなりブート画面がこれです。
テンションあがります!
f:id:toncrimentan_w:20210701095647p:plain



ダメージ床)
BP_Spike

f:id:toncrimentan_w:20210701095721p:plain

床のとげのモデルは、おそらくジオメトリで製作したものと思われ、
9つのとげモデルを1メッシュとしていました。

f:id:toncrimentan_w:20210701095747p:plain

ダメージ部分はボックスコリジョンコンポーネントですね、
オーバーラップイベントとしてGetPlayerCharacterでプレイヤーかどうかを判別し
ApplyDamageノードを利用しダメージをあたえている。
ただそれだけの処理のようです。

f:id:toncrimentan_w:20210701095830p:plain


落下床)
BP_FallingFloor

f:id:toncrimentan_w:20210701095956p:plain

コリジョンのワイアーフレームの太さはこちらのLineThicknessで変更できます。
(これはとても利用価値のある有益な情報です!!)

f:id:toncrimentan_w:20210701100024p:plain

ボックスにオーバーラップすると
SetTimerByEventノードを利用し一定時間後、物理を有効にすることで落下させています。

f:id:toncrimentan_w:20210701100110p:plain

落下後レベルをリスタートすることなく、
一定時間後落下床を元の場所にもどし再開する。非常に丁寧な作りになっています。
(しっかりしています)

f:id:toncrimentan_w:20210701100144p:plain



アニメーション付 落下床)
BP_FallingFloor_WithAnim

f:id:toncrimentan_w:20210701100244p:plain


落下床のアニメーションは、
タイムラインか?と思いきやSetTimerByEventを利用した、
一定時間ごとにメッシュの向きをランダムで変化させることにより作成しています。
(なんかアニメーションがカワイイです!)

f:id:toncrimentan_w:20210701100350p:plain



移動床(2点間))
2点の間を補完する移動床です。

f:id:toncrimentan_w:20210703183449p:plain


コンストラクションスクリプト
TimeLineComponentに対して、PlayRateを利用しタイムラインの再生速度を指定しています。
(タイムラインの再生速度指定方法は実は知りませんでした。あるだろうけども)

f:id:toncrimentan_w:20210703184329p:plain


StartPos GoalPos変数に
インスタンス編集可能
・3Dヴィジェットを表示
の指定を行うことで、ビューポート内でマウスで編集可能にしています!
(こんな方法知らなかった!!)

f:id:toncrimentan_w:20210703184555p:plain



移動床(スプライン))
スプラインの上を補完する移動床です。

スプラインコンポーネントをいじることで、
移動ルートを変更することができます。
f:id:toncrimentan_w:20210703184740p:plain

スプラインはGetLocationAtDistanceAlongSplineノードを利用して
スプラインの指定した距離上の座標を取得することができます。
(個人的には、実は2点間移動床の方が新しい発見がありました)

f:id:toncrimentan_w:20210703184931p:plain



ジップライン)
BP_Zipline

f:id:toncrimentan_w:20210703193339p:plain

コンストラクションスクリプトでは
スプラインコンポーネントと開始位置と終了位置に
自動的に接触ボリュームが配置されているようにしています。

f:id:toncrimentan_w:20210703193318p:plain

このように接触ボリュームがアタッチされます

f:id:toncrimentan_w:20210703193626p:plain


さらにコンストラクションスクリプトでは
スプラインコンポーネント上にスプラインメッシュコンポーネントを追加しています。
これは最終的な挙動には変わらないのですが、
ジップライン上にケーブルが貼っているように見た目上指定しています。

f:id:toncrimentan_w:20210705023709p:plain

こんどはこっちの方です。
見た目上のケーブルを作っています。
キングダムハーツスノーボードステージの空中を張ってるやつとかこれなのかなぁ)

f:id:toncrimentan_w:20210704094056p:plain



ターザンロープ)
BP_SwingRope

f:id:toncrimentan_w:20210705010007p:plain

ロープをつかんだ判定。
ロープの持てる部分にボリュームがあるようにはしていません。
※エリア内に入ったら、ロープのつかめる部分が遠かろうがつかめるようになっています
f:id:toncrimentan_w:20210705010216p:plain

そして、Tickでは
ボリュームにオーバーラップしてから、エンドオーバーラップするまでの間
プレイヤーのCharacterMovementに対しAddForceで移動させるようにしています。
f:id:toncrimentan_w:20210705010323p:plain
向きもその移動の方向に合わせています。
f:id:toncrimentan_w:20210705010347p:plain

ではこのケーブルは何なのか?
ターザンロープとはケーブルに捕まるものではないのだろうか?
そう思う人もいるかと思います。
しかしながら、このケーブルはただの飾りです。見た目です。
※ケーブルなしでも透明なターザンロープにつかまりゲームが実現できる。
 そのうえで、見た目としてプレイヤーにつなげているだけのものになります。
f:id:toncrimentan_w:20210705010433p:plain

ボリューム内に入った時にケーブルをプレイヤーに対してアタッチしています。
f:id:toncrimentan_w:20210705010628p:plain

f:id:toncrimentan_w:20210705010653p:plain

そのほかBP_SwingRopeでは、
話した瞬間ふわっと飛ばすとか、こだわりの処理が含まれています。
つまり、無くても動く処理も含まれています。
(なかなかの大作ギミックだ)



ヴィジェットBPの生成)
WBP_InGameHUD
f:id:toncrimentan_w:20210705013012p:plain

スコアなどのヴィジェットBPはどこで生成するべきか?
ゲームモードで生成しても動くし、プレイヤーのBPで生成しても動く、
多くの参考書ではレベルBPで生成しているものも多くあります。

サンプルでは、
「ゲームモードで生成しています」

スコア表示は、ゲームのルールに関数ものなので
ゲームモードのBPで生成する作りにあるのは適切と思います。

f:id:toncrimentan_w:20210705013051p:plain



エネミー)
BP_Enemy
f:id:toncrimentan_w:20210705020410p:plain

まずビヘイビアツリーは使用していません。
ビヘイビアツリーは難しいと思うし、必要なゲームでもないです。
(サンプルが使用していないのだから、今後製作するゲームにおいて、
 ビヘイビアツリーは利用しない。というのも重要な選択肢とおもいました。)

敵の視覚に入った判定、
サンプルではボリュームを利用して、敵に見つかったかどうかを判別しています。
(一般的にはレイトレースを利用する場合もあります)
f:id:toncrimentan_w:20210705020506p:plain

見つかったら、
ルート移動と弾を発射を実行しています。

ルート移動はAIMoveToノードを利用しています。
f:id:toncrimentan_w:20210705020543p:plain

発射した弾に当たったPCは、BP_Playerで
SetAllBodiesSimulatePhysics、SetCollisionEabledノードを利用しラグドール化しています。
また入力の無効化はPlayerControllerのDisableInputノードを利用しています。
f:id:toncrimentan_w:20210705020600p:plain

またエネミーからプレイヤーへの攻撃は
当たったらダメージというもの製作しています。

敵死亡時の処理、
StopMovementを利用し移動を停止
f:id:toncrimentan_w:20210705022016p:plain

死亡演出は少々カワイイ死亡処理を採用しているようで、
頭とボディにわからたエネミーを
物理に任せてバラバラになるようにしてあります。カワイイ
f:id:toncrimentan_w:20210705022704p:plain




ゴール)
BP_Goal

ゴールBPに接触すると、
SetGlobalTimeDilationノードを利用しスロー演出をいれています。カッコイイ
f:id:toncrimentan_w:20210705022342p:plain



ヴィジェット
WBP_Result

BackgroundBlueを利用して
背景をぼかすような処理をしています。
f:id:toncrimentan_w:20210719224429p:plain
実際こんな感じに表示されます。
f:id:toncrimentan_w:20210719224459p:plain



Spacer
7月14日に放送されたアンリアルクエスト解説編中級・上級によると
https://www.youtube.com/watch?v=xxFZraWma68
こんな風にVerticalBoxとHorisontanBoxにSpacerを組み合わせてキレイにレイアウトを作っていた。
f:id:toncrimentan_w:20210719225118p:plain



解説編中級・上級の動画を見ていて初めて知ったのがこちら、
デバッグフィルタを指定することで実行中に変数の中身を見れるということでした。
これはとても有益な情報でした。
f:id:toncrimentan_w:20210719225313p:plainf:id:toncrimentan_w:20210719225316p:plain





工事中