UNREAL→LABØ

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

【第11回】移動する足場

 

概要

今回もギミックを作成とレベル配置を行いながら学習を進めます。

 

簡単な「Interp Movement」コンポーネントを中心に学習していきながら、知識として「ワールド」と「ローカル」座標について理解を深めていきます。また、変数をインスタンス編集可能にしてレベル上で調整する方法も合わせて学びましょう。

 

f:id:miccak:20210428134459p:plain

 

 

アクタを作成する

開始ポイントに対岸まで「一方通行に動く足場」を作ります。

 

「移動するアクタ」系のギミックは汎用的でさまざまな状況で使われます。
実現方法はいくつかありますが、簡単な方法からためしてみることにしましょう。

 

こういったギミック作成するときは、「足場アクタは、指定されたA地点からB地点まで一定速度で移動する」「B地点まで到達した足場アクタは、A地点にワープして戻る」といったように機能を細分化して考えましょう。
お馴染みの「直線で動くだけの」アクタですね。

  

足場用の Static Mesh を用意しておきます。

用意が無い場合は、ジオメトリブラシから、アクタ用メッシュを作成しておきましょう。

 

作成方法は過去回を参照してください。
もちろん、アセットを買ってインポートしたり、移行してきても構いません。

 

「追加/インポート」→「ブループリントクラス」→親クラス「Actor」を選びましょう。
名前は自由に設定してください。ここでは「BP_Step」としました。

 

f:id:miccak:20210428135118p:plain
f:id:miccak:20210428135136p:plain


ダブルクリックしてブループリントエディタを開きます。

 

さっそくメッシュを設定していきます。
コンポーネントパネルの「コンポーネントを追加」から「Static Mesh」を選びます。

 

f:id:miccak:20210428135305p:plain

 

名前をわかりやすく変更しておきます。

 

f:id:miccak:20210428135400p:plain

 

コンポーネントパネルから、追加したStatic Meshコンポーネントを選択してください。
下図のように、詳細パネルからメッシュを設定しましょう。

 

f:id:miccak:20210428135513p:plain

 

設定したら、キャラクターとのサイズ差を確認するため、レベルに配置してみます。

 

テスト用のレベルを作成し、配置して確認します。

 

サイズ感を確かめるのも目的なので「DemoMap」に配置してみるのも良いでしょう。

 

f:id:miccak:20210428135923p:plain

 

大丈夫そうです。サイズ感などが気に入らなければ、ブループリントの詳細パネル「トランスフォーム」項目からスケールを変更しておきます。ジオメトリを変換して使っているのであれば、コピー元のジオメトリの拡縮を行って再度メッシュ化しても良いかもしれません。

f:id:miccak:20210428140036p:plain

 

目下のところは、このStaticMeshに設定したコリジョン以外のコリジョンは追加しないことにします(メッシュそれ自体のコリジョンを使って足場とする)。

 

コリジョンはメッシュではなく個別に設定したい!という場合は、コンポーネントパネルの「コンポーネントを追加」からコリジョン用のメッシュを追加するか、任意の「Box Collision」などを追加してください。

その際には、メッシュ自体のコリジョンは消して置くほうが無難です。またコリジョンをルートにする方がいいでしょう。
下図は個別にボックスコリジョンを追加した様子です。

f:id:miccak:20210428140709p:plain

 念のためメッシュ自体のコリジョンがあるかも確認しておきましょう。

メッシュにコリジョンを追加する方法は過去の連載を参照してくださいね。

 

また、事前準備として、コンポーネントの可動性が「ムーバブル」であるかも確認しておいてください。

 

f:id:miccak:20210428140947p:plain


ブループリント上の詳細パネルで各コンポーネントの可動性を確認できます(レベル上のアクタの詳細パネルではなくブループリント内の詳細パネルです。間違えないように注意しましょう)

 

起動中に移動するコンポーネントは、すべてこの設定が必要です。

 


移動機能を付与するコンポーネント

さて、さっそくブループリントを使って移動処理を組んでいきたいところですが……


実のところ、UE4にはデフォルトで足場にピッタリな「アクタを移動させる」機能を持つコンポーネントがあります。ブループリントで移動させる方法は拡張性はあるのですが、今回のような単純な移動の場合は以下で紹介する方法で事足りそうです。


難しい方法は今後の章で学ぶとして、ひとまず簡単な方法を試してみましょう。

 

コンポーネントパネルの「コンポーネントを追加」から「Interp To Movement」コンポーネントを選択して設定します。このコンポーネントはルートコンポーネントを指定位置まで移動させる機能を持ちます。

f:id:miccak:20210428141116p:plain

f:id:miccak:20210428141141p:plain


「Interp To Movement」 コンポーネントを選択して、詳細パネルを確認します。
主に使用する機能を一通り説明します。

 

「コントロール」> Duration

移動開始地点から終了地点まで移動するのにかかる時間を指定します(単位:秒)

 

f:id:miccak:20210428141248p:plain

 

テストとして、3~5くらいの値を指定してみましょう。

f:id:miccak:20210428143045p:plain

 

「コントロール」 > Control Points

移動する各区間の位置を指定する項目です。
「+」ボタンを押してスタート地点となるゼロ地点を追加してみましょう。

f:id:miccak:20210428141528p:plain

 

位置は「Position Control Points」で座標指定します。

 

「Position Is Relative」 というチェックは、移動する際にルートコンポーネントからの相対距離を使用するかどうかです。


チェックを入れていればレベルに置いたアクタの位置を原点(0地点)として指定位置まで移動します。チェックを外すとワールド座標の原点を参照するようになります。

 

f:id:miccak:20210428142015p:plain

 

例えば、「Control Point 0」の座標に(X:500,Y:0,Z:0)と指定した場合、「Position Is Relative」のチェックを外しているとゲーム起動後即座に、ワールド座標の(X:500,Y:0,Z:0)にアクタが移動します。

チェックをいれていると配置された場所から換算して(X+500 )の位置にアクタが移動します。

 

今回は置かれた地点を原点としたいので、チェックを入れた状態で作成します。

つまり「現在地点から相対的にどちら方向へ移動するか」を設定したいので、「Control Point 0」の座標はすべて0にしておきます。

 

再度「+」を押して、2番目の「Position Control Points」を設定してください。

 

ここで移動先の場所を指定しましょう(正確には「2地点目の場所」)。
直線的な動きなのでポイントは合計2個で足りそうですね。

f:id:miccak:20210428143118p:plain

 

これで基本的な設定は完了です!
テスト用のレベルで、アクタを下図のような位置に設定して確認してみます。

 

アクタの動作だけを見たいときは「シミュレートモード」で起動するのもオススメです。プレイアイコンの右側にある▼を押して「シミュレート」を選びましょう。
プレイヤーが生成されずに動作だけ確認できるはずです。

 

プレイボタン右側の「▼」を押して、モードを「シミュレート」にして開始します。
すでにプレイボタンが歯車のマークであればそのまま押しても大丈夫。ブループリントエディタのツールバーからシミュレートボタンを押すと、プレイ画面に自動で切り替わらないので注意してください。

f:id:miccak:20210428143244p:plain

f:id:miccak:20210428143515g:plain

正しく動いたでしょうか。
 
「Position Is Relative」がONなので、アクタから相対的な距離を指定していることに注意してください。アクタの位置を0起点として、そこからX方向に移動しています。

 

f:id:miccak:20210428143824p:plain


上図のように、アクタとワールドの軸が一緒なら同じ方向に移動します。

しかし、以下のようにアクタの軸(Yaw)を45度程度回転させて配置した場合、アクタは自身のX軸方向に500進みます(目的地に到着したときの位置はX353Y353くらいでしょうか)。

f:id:miccak:20210428143905p:plain


今後もアクタの座標を書き換えることが多くなりますが、その際は扱っているのがワールドの座標なのか、アクタの(Root)からの相対的な座標なのか、注意しながら実装していきましょう。

 

 

「ビヘイビア」>「Behaviour Type」

移動範囲(距離)を決めましたので、移動方式を決めていきましょう。
移動方式は、詳細パネルの「ビヘイビア」> 「Behaviour Type」から設定できます。

 

f:id:miccak:20210428144059p:plain

 

One Shot :デフォルト状態。目的地まで到達したら停止する
One Shot Reverse:目的地まで到達したら、開始位置まで戻って停止する。
Loop Reset:目的地まで到達したら距離をリセットして繰り返す。
PingPong:目的地まで到達したら開始地点まで戻る移動を繰り返す。

 

今回は常に同じ方向にループ移動してほしいので「Loop Reset」を選びました。

 

f:id:miccak:20210428144158p:plain

 

プレイして確認してみましょう。

f:id:miccak:20210428144618g:plain


問題なさそうならメインのレベルに配置しておきます。

 

レベル上の動かしたい位置に置いて、詳細パネルから秒数(Duration)や距離(Position Control Points の2番目)を調整します。

youtu.be

 

まだ調整は必要そうですが、ひとまず移動できるようになりましたね。

 

 

複数個の足場を設置する

さて、うまく動くようになったのは良いものの、足場に乗り遅れると次の足場が出るまで待つのが面倒に感じてくるようになりました。実際に動かしてみてわかるという状況はしばしばですね…!


ひとまず解決策はないか考えてみましょう。

 

安直ですが、「複数個の足場を用意して動かす」ことを思いつきました。

やってみましょう。

 

しかし「Interp To Movement」機能の関係上、中間地点に複数個置いたとしてもスタート地点に戻る性質があるため、うまく動作しそうにありません。

 

もちろん、ブループリントで座標移動させる実装に切り替えればサクッと問題解決できるのですが、それは後ほどご説明するとして、現状の「Interp To Movement」コンポーネントを使って解決方法をさがしてみます。

 

スタート地点に足場を複数個設置しておいてアクティベート管理と「Delay」で移動開始タイミングをずらす方法を試してみます。

 

 

コンポーネントの起動(アクティベート)を管理

すべてのコンポーネントは、それが「使用する(される)状態か?」をアクティベーションとして管理しています。

 

「Interp To Movement」コンポーネントアクティベーションをOFF状態にしておけば、それがゲーム中のどこかでONになるまで機能しなくなるはずです。

 

コンポーネントパネルで「Interp To Movement」コンポーネントを選択して、
詳細パネルの「アクティベーションといという項目を確認しましょう。
チェックをOFFにします。

 

f:id:miccak:20210428150021p:plain

 

プレイして、開始時すぐに動き出さないことを確認しましょう。
コンポーネントがOFFの状態(非活性)となっていることがわかりますね。
 
時間差でONになるようにブループリントで設定します。
今回なるべくブループリントは使わない予定でしたが仕方ありません。
とはいえ処理はごくわずかです。今まで使ったノードばかりなので安心してください。

 

ブループリントグラフを開き、「Begin Play」ノードを確認してください。

その付近にコンポーネントパネルから「Interp To Movement」の参照をドラッグ&ドロップします。

f:id:miccak:20210428150159g:plain

つづけて、その参照ノードからワイヤーを伸ばして「Set Active」ノードを設置します。

f:id:miccak:20210428150243p:plain

 

「Set Active」ノードは、ターゲットに接続されているコンポーネントをアクティブ(起動)状態にするノードです。


ほぼすべてのコンポーネントをターゲットにできるノードですので、覚えておきましょう。

 

「New Active」のチェックをTrue(ON)にします。

f:id:miccak:20210428150346p:plain

そして、「Delay」ノードを挟んで、ノード同士を接続します。

f:id:miccak:20210428150435p:plain

 

適当な秒数をDelayに入れてプレイして動作を確認してください。
Delay後に動き出すことがわかりますね。
 
しかし、このままでは設置したアクタすべて同じDelay秒数なので意味がありません。
Delay秒数指定部分を「インスタンス編集可能」変数にして、設置後にユニークな値に変更できるようにします。
Duration入力ピンからワイヤーを伸ばして「変数へ昇格」を選択して変数にしましょう。

f:id:miccak:20210428150626p:plain

名前は適当につけておきます。
 
コンパイルしたあと、詳細パネルから「インスタンス編集可能」にチェックをいれましょう。
このチェックが入ることで、レベルに置かれたアクタの変数を独自に変更できるようになります。
 
f:id:miccak:20210428150853p:plain
 

コンパイルしてから、レベル上で確認してみましょう。

詳細パネルから値を変更できるはずです。

f:id:miccak:20210428151111p:plain

 

すぐ近くにもう1,2個コピーして移動距離やDelay間隔を変更します。

f:id:miccak:20210428151613p:plain

f:id:miccak:20210428151720p:plain

間隔の調整は必要そうですが、懸念した事態は緩和されたようです。


難易度を下げる(乗ったときに動くように改良する)

目標とするギミックは概ね完成しましたが、何度かテストプレイをしているうち「最初に乗るのが忙しくて周りを見る余裕が無いかもしれない」ことが気になりだしました。
今は殺風景ですが、いずれはプレイヤーに周囲を見回してもらってヒントを見つけてもらったり、世界観を見てもらいたいものです。
また、最後に足場が土台に潜ってしまい振り落とされる仕様も、初心者には若干難しいように感じました。
 
そこで、以下のように修正してみることにします。
現状でもステージは進められますので、余裕があればためしてみてください。
  • プレイヤーが乗るまで足場を動かないようにする。
  • 足場が目的地点に到達したらスタート地点に戻って停止する。
  • 再度プレイヤーが乗れば動き出す。
 
まず行ったりきたりする動作に変えるため、三個あったアクタをひとつにしました。
乗るまで動き出さないので、少しだけ前方に動かします。
f:id:miccak:20210507234047p:plain
足場の目的地が少し短くなるので「Control Point」の座標も調整します。

f:id:miccak:20210508000445p:plain

デフォルトのパラメータも変更します。
「One Shot Reverse」にして、目的地に着いたら元の位置に戻って終了するようにします。
f:id:miccak:20210507234017p:plain
 
自動で移動を開始しないよう、「Begin Play」イベントを切断します。

f:id:miccak:20210508003428p:plain

さて、キャラクターが乗ったら移動開始するようにします。
コリジョンを使って「乗っているか(存在するか)」を判断しましょう。
コンポーネントパネルから「Box Collision」を追加します。
f:id:miccak:20210508000702p:plain
f:id:miccak:20210508000748p:plain

 

相対位置とサイズを変更します。コンポーネントパネルで「Box Collision」を選択状態にして、詳細パネルの「トランスフォーム」と「シェイプ」から設定します。

f:id:miccak:20210508003744p:plain

 

オーバーラップイベントを追加します。
詳細パネルのイベント項目から「On Component Begin Overlap」を追加します。

 

f:id:miccak:20210508003428p:plain
f:id:miccak:20210508003533p:plain

 

キャラクターの行動不能エリアを作成したときと同じように「Cast~」ノードを使ってキャラクターがオーバーラップしたかを判断します。

f:id:miccak:20210508003933p:plain


「Set Active」を接続します。

f:id:miccak:20210508004835p:plain

 

これでキャラクターがコリジョンに入ったら移動を開始するようになります。

……が、実のところこのままでは戻ってきて停止したあと、再び乗っても移動を開始しません。
これは、すでにControl Pointをすべて実行したと判断されているからですね。

 

そこで、開始位置にリセットするノード「Restart Movement」を使ってみましょう。

ゲットした「Interp Movement」コンポーネントからワイヤーを伸ばし「Restart Movement」を検索して配置します。

f:id:miccak:20210508005932p:plain
f:id:miccak:20210508005945p:plain

ノードの引数に1が入っていると基本の速度でリセットされます。

 

これで望む動作になりましたね!

と言いたいところですが、まだ問題があります。プレイするとわかりますが、足場の上でジャンプするたびオーバーラップが発生して「Restart Movement」が実行されてしまうんですね。

このままではジャンプのたびに元の位置に戻ってきてしまう欠陥ギミックです。

オーバーラップのイベントをつくる時にありがちなケースです。
オーバーラップは入るたびに呼ばれることを覚えておきましょう!

 

フラグ変数を使って一度だけ発生するようにしても良いのですが、今回は「Do once」ノードを使ってみましょう。任意の場所を右クリックして検索して配置してください。

f:id:miccak:20210508011033p:plain

f:id:miccak:20210508011108p:plain

このノードは、以降の処理を一度だけ実行させます。

さらにリセットも可能なので、戻ってきたときにリセットするようにします。

 

「Interp Movement」には「Stopしたこと」を検知するイベントがあります。
コンポーネントパネルを選択して、詳細パネルのイベントから「On Interp to Stop」を押しましょう。

f:id:miccak:20210508011504p:plain
f:id:miccak:20210508012517p:plain

 

この実行ピンを「Do once」ノードの「Reset」ピンに接続します。

f:id:miccak:20210508013003p:plain

 

これでInterp(移動)が終了(Stop)するたび、Do onceがリセットされて「On Component Begin Overlap」イベントを実行できるようになりました。

 

プレイして確認してみましょう。




さて、本当の本当に今回はこれで以上です!

 

もっと気になる部分や調整したい部分もあるかもしれませんが、それは別途調べていただくか、今後の学習で補完していくことにしたいと思います。それに、この「Interp Movement」コンポーネントはあまり融通がきかないので、無理して改修するのもオススメできません……。というか、「簡単に実装する」という目的からも外れてしまいまうような気もしますね。拡張性のあるつくりは、今後学習する方法を使う方がよさそうです。

 

お疲れさまでした!
 
 

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