UNREAL→LABØ

Unreal Engine4の情報をまとめます。

【第17回】インタラクトするギミック②

 

概要

前回はプレイヤーがインタラクトできるレバーハンドルの処理を作成しました。

f:id:miccak:20210514193458p:plain
f:id:miccak:20210518140415p:plain

 

今回はそのインタラクトをトリガーにして、レベル上にアクタを生成する処理を作成します。

生成したアクタは移動させながらアイテム付近まで移動させて、画面外まで移動した足場は消してしまうことにします。また、レバーハンドルの処理を何度も実行できるようにも調整しましょう。

f:id:miccak:20210519132516p:plain

移動する足場に乗って移動しすぎないよう、レベルの配置を少し調整しました。

 

 

トリガーによってアクタを生成する

特定の場所にアクタを生成して、指定した位置まで動かします。

メッシュを作成しておきます。
その上に乗って移動できるようにしたいので、ひとまずメッシュにコリジョンを付与します。

f:id:miccak:20210518142202p:plain

 

生成する対象となるブループリントを作成します。
ブループリントは「Actor」クラスです。

f:id:miccak:20210518135155p:plain

 

ブループリントを開いて、Static Meshコンポーネントを設定してください。

f:id:miccak:20210518142326p:plain

 

つづいて、落下ポイントのブループリントを作成します。

このブループリントが指定した場所に、上記で作成したブループリントアクタを生成させます。

「Actor」クラスブループリントで作成してください。

f:id:miccak:20210518143520p:plain

 

ブループリントを開きます。
コンポーネントパネルで「コンポーネントを追加」します。
「Arrow」コンポーネントを追加してください。

f:id:miccak:20210518144228p:plain

 

これはプレイ時に表示されない「見えない目印」として機能します。位置を指定するのに使ったり、ルートからの相対距離を参照するなど、使い勝手の良いコンポーネントです。

 

続けて、イベントグラフを開きます。
カスタムイベントを作成しましょう。

f:id:miccak:20210518152816p:plain


右クリックして、Spawn Actor と検索します。
「クラスからアクタをスポーンします」というノードを配置しましょう。

これは特定のアクタを生み出す(スポーンする)処理です。

f:id:miccak:20210518152850p:plain
f:id:miccak:20210518152901p:plain


このノードを使用するときは必ず生成するブループリント(Class)と、生成する位置角度スケール(Transform)を指定しなければなりません。

Classのドロップダウンから、先ほど作成したブループリントを指定しましょう。

f:id:miccak:20210518152926p:plain

Tranform(位置、角度、スケール)は、ArrowコンポーネントのTransformを参照して使います。

Arrowコンポーネントの参照をゲットしてください。
そこからワイヤーを伸ばし「Get World Transform」を配置して接続しましょう。

f:id:miccak:20210518153150g:plain

 

これで生成イベントができましたね。

f:id:miccak:20210518153251p:plain


生成タイミングは、レバーを下ろしきったタイミングにしたいと思います。
「Finished」時に発行するイベントディスパッチャーがあるのでそちらを使いましょう。

 

イベントディスパッチャーをバインドするための参照を得る方法はなんでも構いません。
レベル上にひとつしかないので、ここでは「Get All Actors of Class」で検索して受け取ったものを変数に代入します。複数ある場合は、区別する変数を作成して判断しましょう。

f:id:miccak:20210518174542g:plain

 

「For Each Loop」のCompleted以降で、バインドを呼び出します。
Spwanするイベントに接続しましょう。

f:id:miccak:20210518174907p:plain

念のためSpawn時にコリジョンが衝突していても生成されるよう、引数「Collision Hnading Override」を「Always Spawn」に変更しておきました。

f:id:miccak:20210518175052p:plain


確認用のレベルに配置してテストしてみます。

f:id:miccak:20210518175445p:plain

無事生成されるようになりました。

f:id:miccak:20210518180657p:plain


 

生成したアクタを動かす

次に、生成されたアクタを動かす処理を入れてみたいと思います。

f:id:miccak:20210519133737p:plain

動かし方はどのような方法でも構いません。
Tickで単純に動かす方法や「Interp Movement」を使っても良いですし、タイムラインや、Splineを活用しても良いかもしれません。

いくつかの方法を検討してみましょう。

 

物理落下を試してみる

ひとまず、(プレイヤーから見えない位置で生成しますので)生成後はプレイヤーが移動可能な位置まで移動させたいですね。


ためしに物理機能を使って、生成したアクタを自由落下させてみましょう。

 

落下するアクタのブループリントを開きます。

準備としてコンポーネントパネルのRoot(親)をメッシュにしておきます。

f:id:miccak:20210518181153p:plain

 

メッシュを選択した状態で詳細パネルの「物理」項目にある「Simulate Physics」のチェックをONにします。これで、このブループリントの物理機能が有効になりました。

f:id:miccak:20210518181318p:plain

 

プレイして落下することを確認してください。

f:id:miccak:20210518181450p:plain

 

あとは、生成したアクタだけを受け止める(=プレイヤーを無視する)地面を設置すれば足場として機能しそうですね。

 

コリジョンだけのブループリントを作成して地面とするのもいいでしょう。

f:id:miccak:20210518182226p:plain

 

プレイヤーを受け止めないコリジョン設定は、上図のようにコリジョンの「コリジョンプリセット」を「Custom」に変更して、「Collision Enabled」を「Collision Enabled(Query and Physics)」に。コリジョンレスポンスのチェック項目を「Spawnしたアクタのみをブロック」するように変更するだけです。

ちなみに物理機能がONになるとコリジョンは自動的に「PhysicsBody」に変更されます。

f:id:miccak:20210518182310p:plain
f:id:miccak:20210518183323p:plain


うまく停止しましたね(プレイヤーはコリジョンを素通りすることも確認できました)。
このように、コリジョン反応の分類をルールにあわせて適宜カテゴライズする方法は今後も使う機会が多いので覚えておきましょう。

 

もっと簡単な方法としては、適当なメッシュを置き、コリジョンの設定を変更して「Visibility」をOFFにするだけでも同じように機能させることが可能です。余裕があれば、どちらもためしてみてください。

f:id:miccak:20210518182746p:plain

 

つづいて、落下完了したら物理を停止させておきましょう。
アクタがバウンドしなくなり、物理による予想外の動きが起きなくなります。
その後、移動させる処理を実行するためにも必要です。

 

落下(の衝突)を検知するイベントを作成します。


今まではOverlapを検知してイベントにしていましたが、ここではHitイベントを使ってみます。

コンポーネントから「StaticMesh」を選択してください。
詳細パネルのコリジョン項目にある「Simulation Generates Hit Events」をONにします。
これでヒットイベントを検知できるようになりました。

 f:id:miccak:20210518184052p:plain

 

イベントから「On Component Hit」を選択してヒット時に通知されるイベントを生成します。

f:id:miccak:20210518184208p:plain
f:id:miccak:20210518184326p:plain


ヒットイベントの「Other Actor」ピンからワイヤーを伸ばします。

ヒットしたものが指定のものであれば、処理を継続するようCastで判断しましょう。
上記でブロック用のブループリントを作成しましたので、それを選択しました。

 

f:id:miccak:20210518184730p:plain

 

念のため、ヒット後の処理が何度も呼ばれないように「Do Once」をはさみます。

これは以降の処理を一度だけ使用できるようにするノードですね。

 

そして、ヒットが実行されたら物理機能を切ります。Static Meshコンポーネントの参照をゲットして、そこからワイヤーを伸ばして「Set Simulate Physics」ノードを検索して配置します。

f:id:miccak:20210518185234p:plain
f:id:miccak:20210518185252p:plain

 

さて、ひとまずこれで任意の位置まで生成したアクタを移動させることができましたね。

 

メインでプレイするレベルに置いて、確認していきましょう。

ここから画面外に移動させます。

f:id:miccak:20210519141152p:plain

今まで学習したどの移動方法でも実現できそうですが、今回は開始時点やアイテムの足場付近では移動速度を落とすようなユーザビリティにも気を配ってみましょう。

どんな移動方法がベターでしょうか?

できなくもなさそうですが、「Interp Movement」コンポーネントや「Tick」イベントのみを使って移動させる方法では、調整が少々面倒そうです。

簡単なのはタイムラインによる移動、次にスプライン移動でしょうか。

 

作成してみます。

 

タイムラインによる移動

タイムラインを作成します。

f:id:miccak:20210519144038p:plain

 

タイムラインエディタを開きます。

X方向に動かしながらZ方向に動かしますので、今回は「Vector」値のグラフを作成しましょう。
「V+」を選択します。

f:id:miccak:20210519144422p:plain
f:id:miccak:20210519144646p:plain

グラフ左上にある目や鍵アイコンを使ってX値とZ値を設定していきます。

値は後々調整することになりそうですが、ひとまずプレイに支障がでない程度に。
グラフは面倒にも思えますが、慣れれば短時間で設定できるようになります。 

f:id:miccak:20210519160417p:plain

X軸
00秒:0
05秒:0.175
11秒:0.45
40秒:1.0

Z軸
00秒:0
08秒:0.45
11秒:0.5
20秒:0.6
40秒:1.0

それぞれのLerpに使用するAlpha値を設定しました。

 

タイムラインはカスタムイベントで呼び出します。

Update部分の処理を書いていきましょう。

Physicsを切ったあとにその地点の座標を取得(Default Location変数に代入)し、タイムライン実行時に差分を加算した値に書き換えています。タイムラインを稼働させるまでに若干のディレイを設けます。

そして、Finish部分で「Destroy Actor」ノードを使い、アクタを削除します。

f:id:miccak:20210519163759p:plain
「Get Actor Forward Vector」と「Get Actor Up Vector」は足場アクタの前方と上方のVectorを取得するノードです。アクタの向きにそって動かすために使用します。
もしワールド軸で移動させる場合には不要です。

 

確認してみましょう。うまく動いているでしょうか?

Spline Actor を使った移動方法も章の最後に記載しています。
興味があればチャレンジしてみましょう。

 

 

バーハンドルを戻して再度使えるようにする。

足場の出現が一度だけでは難易度が高すぎます。

生成後、一定時間経過したら再度レバーハンドルを操作できるようにしましょう。

 

バーハンドルのブループリントを開きましょう。

f:id:miccak:20210519164758p:plain

タイムラインの「Reverse(巻き戻し)」機能を使います。
Fnished時、順再生のときだけイベントディスパッチャーが呼ばれるようにします。

 

f:id:miccak:20210519170004p:plain

 

早く戻りすぎるとアクタが重なってしまうので、ディレイをかけて「Reverse」を実行します。
「Set Play Rate」で、戻りレバー速度を調整してメリハリもつけました。

f:id:miccak:20210519170602p:plain

順再生でないときは、実行フラグの変数(Is Interacted)を「False」に戻します。

 

テストプレイで確認してみましょう。

 

今回は、これで以上です!
現時点ではアニメーションとの連動もなく、負荷なども想定せず単純にイベントを呼び出しただけですが、改良すればよりスマートで汎用的なイベントに改良できますので、これで完成とせず、さまざまな方法をためしてみてください。

お疲れさまでした!

 

 

プロジェクトのダウンロード

drive.google.com