BLOGブログ

2024.12.04UE5UE/ 初心者向けUE/ Blueprint

[UE5] インタラクト可能なモノの量産に役立つBPを作ってみよう

執筆バージョン: Unreal Engine 5.4

こんにちは。ゲーム開発において「プレイヤーがインタラクトすると動くモノ」を作ることがよくあると思います。しかしながら、ドアや棚や引き出し等々、それぞれのBPを都度組むとなると大変です。

本記事はそんな時、ちょっとだけ楽できるかもしれないBPの作り方を紹介します。

 

完成イメージ

プレイヤーが近づくとUIが表示され、案内通りインタラクト(Fキー)を押すとドアなどが動いています。

 

準備

今回はThirdPersonテンプレートにStarterContentを追加したプロジェクト上で実装しました。

 

実装:親クラス

まずはコンテンツブラウザ上で右クリックし、BluePrintクラスを選択します。そしてダイアログ一番上の[Actor]を選択後、作成したBPに「BP_InteractBase」と名付けました。

このBPを、「プレイヤーがインタラクトすると動くモノ」の「親」として実装し、ドア、引き出し、キャビネットなどはその「子」として後に実装していきます。

BP_InteractBaseをダブルクリックで開き、Componentsタグの[+Add]から以下のコンポーネントを追加します。

① Widget (名前:Icon) – 「F」のアイコンを表示するため。

② BoxCollision (名前:Box) – プレイヤーがインタラクトできる範囲に来たかを判定するため。 

③ StaticMesh (名前:MeshMovable) – インタラクト後にメッシュを動かすため。

 

・検索機能を使うと便利です。

 

まずは①Iconに登録するウィジットから作ります。コンテンツブラウザ上で右クリックし、[Interface] → [Widget BluePrint] → [User Interface]を選択後、作成したウィジットBPに「WBP_Icon」と名付けました。

このWBP_Iconをダブルクリックで開き、Designer上で好きなアイコンを作ります。本作例では簡単に、黒いImageの上にTextのF(インタラクトボタンのF)を表示しています。

WBPの作成が終わったらBP_InteractBaseに戻り、①Iconの詳細パネルのUserInterfaceを以下画像のように編集します。

・Spaceを[Screen]とする事で、UIが2D空間に表示されるようになります。

 

次にプレイヤーが②Box内に入った時のみ、プレイヤーのインタラクトを受け付け、①Iconを表示する機能を簡易的に実装します。

まずはプレイヤーがインタラクトボタンを押したら、他のBPにその事を通知するためのディスパッチャーを追加します。

コンテンツブラウザの /All/Game/ThirdPerson/BlueprintsにあるBP_ThirdPersonCharacterを開いて、次の手順を行います。

①  MyBlueprintパネルの[EventDispatchers]の+ボタンから[OnInteraction]という名前のディスパッチャーを追加

②  EventGraph上でKeyboardEvents(F)を追加後、ディスパッチャーを呼び出す処理を組みます。

これにてBP_ThirdPersonCharacterでの実装は終了です。

 

BP_InteractBaseに戻り、Boxコンポーネントの詳細パネルのEventsタブより[On Component Begin Overlap]と[On Component End Overlap]の横にある+マークをクリックしてイベントを用意します。

このイベントを使って以下のように実装します。

・これにより「Boxにプレイヤーが入った」かつ「プレイヤーがインタラクトボタンを押した」時にE_Interaction_Eventが動作します。

・「Boxからプレイヤーが出た」時にはE_Interaction_Eventは発動してほしくないのでUnbindします。

 

Bind Event, Unbind Eventの部分は以下のようにピンを引っ張り、Search機能を用いると便利です。

StartMeshMoveからは以下のように実装します。

・TimeLineは時間の長さを0~1の範囲で定義しておき、後で2秒、0.5秒と時間の長さを調整できる[PlayRate]関数を用いるのが便利です。

上記の通り、変数を追加しており、Bool : IsClosed は、インタラクトオブジェクトが開閉どちらの状態にあるか判別のために使用し、Float : Movetimespan はインタラクト後にMeshMovableが開閉する時間の間隔を表します。

 

MeshMove関数を新規で作り、以下の実装を行います。

変数のTransfromClosed / Opend : Transform は、インタラクトオブジェクト開閉時のTransformを定めるために使用し、MoveTimeExp : FloatはEaseの指数を調整するために使用し、今回は2.0を設定しています。

以上で本BPでの実装はほぼ完成ですが、インタラクトオブジェクトの開閉時の様子をエディタ上でも確認するために、ConstructionScript上で以下の実装を行います。

変数のTestMoveRate : Float は0~1.0の値制限し、0の時にインタラクトオブジェクトを閉めている状態、1.0の時にインタラクトオブジェクトを開けている状態をエディタ上で確認するために使用し、詳細パネルのSliderRnge, ValueRangeを以下のように制限しています。

以上にて、親クラスの実装は完了です。

 

実装:子クラス

これまで実装したBP_InteractBaseを継承した子のBPを作り、インタラクトオブジェクトを量産する作業を行います。今回は例としてドアを作ります。

まず、コンテンツブラウザ上でBP_InteractBaseを右クリックし、[CreateChildBlueprintClass]を選択後、名前を「BP_InteractDoor」としました。その後BPを開いて以下の作業を行います。

1.ComponentsからStaticMeshを追加し、ドアのフレームメッシュ:SM_DoorFrameを配置します。

2.プレイヤーがドアにインタラクトできる範囲を設定します。そのためにBoxコリジョンの位置・スケールを調整します。

3.インタラクトIconを表示する位置を調整します。

4.MeshMovableのStaticMeshにメッシュ:SM_Doorを登録します。

・MeshMobableのドアの位置等はこれから修正していきます。

 

次にBP_InteractBaseで設定した以下の変数を編集していきます。設定は上部タスクバーの[ClassDefaults]をクリックすると、親クラスの変数デフォルト値を、子クラスの方で書き換え設定することができます。

1.TestMoveRateを0(閉じた状態)にして、ドアが閉じている時の様子を可視化します。その後、TransformClosedを編集し、ドアが閉じている時の位置・回転の値を設定していきます。

2.TestMoveRateを1.0(開いた状態)にして、ドアが閉じている時の様子を可視化します。その後、TransformOpenedを編集し、ドアが開いている時の位置・回転の値を設定していきます。

・これにより、TestMoveRateを0~1.0の間で変動させると、ドアが開閉する様子を確認できるかと思います。

 

3.その他のパラメータを設定します。

 MoveTimeExp : ドアが開閉する動作のEase指数を指定します。これを満足ゆくドアモーションが得られるまで調整します。

 MoveTimeSpan : ドアが開閉する時間間隔を指定します。こちらも満足ゆくドアモーションが得られるまで調整します。

 IsClosed : 今回はTrue固定です。

以上の設定が終わった、ThirdPersonMapに「BP_InteractDoor」を配置し、作例のようにプレイヤーでドアを開閉して動作検証し、好みのモーションを探っていきましょう。
また、同様の手順で他のキャビネットや引き出しのようなモノも実装しています。

 

まとめ

このように親クラスで子クラスに共通する処理を組んでおくと、子クラスの方では変数のデフォルト値を設定するだけで目的の動きを実現できたり、さらに関数のオーバーライド等を活用する事で、子クラスの方でもある程度独立性の高い動きなどが実装できます。

ただ、今回のようなインタラクトBPを使用していてると次のような不満が出てくるかもしれません。(というか、出ます。)

・ドアが開いている状態をゲームの初期状態にしたいのに、出来ない!

・Transform変数を調整してドアの位置・回転とかを調整するのは作業性が悪い!

・引き出しが沢山あるインタラクトBPを作りたいんだけど、これだと一つのメッシュしか動かせない!

是非、このような課題に対し、「どうやったらもっと便利な親クラスを用意できるか?」を考察・実装し、その知見を共有していただければ幸いです!

お目通し頂きありがとうございました。