Unreal Engineの基本的な知識があまりないので、機能紹介も兼ねている機能別サンプルのブループリント通信の中身を見て、複数のブループリント間でどうやってやりとりしたらいいのか見てみた (要はカスタムイベント、イベントディスパッチャー、ブループリントインターフェース)。
確認したバージョン:UE5.2.1
ダウンロード・動かし方
- UEマーケットプレイスのContent Examples in UE Feature Samplesをダウンロードし、UEでプロジェクト作成して起動
- コンテンツブラウザのContent/Maps/Blueprint_Communicationをダブルクリックで開く
機能別サンプルのレベルの構造
- 部屋全体はレベルのアウトライナーに配置された
BP_DemoRoom
で構築される- ブループリントクラスは
Content/Global/DemoRoom/Blueprints/BP_DemoRoom
にある - コンストラクションスクリプト で自分の
Redraw
関数を呼び出し、変数に従って部屋を構築する(プロシージャル) S_RoomSettings
構造体型の配列Rooms
が各部屋の情報(Length
,Width
,Height
など)で、変数がpublic
になっているのでレベルの詳細パネルで変数の値を書き換えるとそれに伴って部屋が再構築されるTestRoom
というレベルもあるので、そちらも見てみるとよいかも
- ブループリントクラスは
- 機能ごとのブースは
BP_DemoDisplay
をベースに作成される- 同じくコンストラクションスクリプトで、
Title
やDescription
などが詳細パネルから設定されて反映されるようになっている
- 同じくコンストラクションスクリプトで、
- ブースで説明する要素はそれとは別にフォルダ分けされずにずらっと並べられている
動作の調べ方
- レベル上に配置されているアクターから調べたいものを選択し、アウトライナーのTypeにある「Edit BP_~」をクリックでそいつがどのBPクラスかわかるので、そのブループリントクラスのイベントグラフを見てどういう処理が書かれているかを調べる
- 他には必要だったらレベルブループリントやポーン側でどう処理してるかを見る
ブースごとの内容
1.1 Basic communication with a target blueprint
方法:対象アクターの変数を持っておき、カスタムイベントを呼び出す
説明文:「この例には、カスタムイベントを介してライトブループリントのオンとオフを切り替えるボタンブループリントが含まれています。 プレイ中にボタンに近づくと、有効になります。」 (This example features a button Blueprint that toggles a light Blueprint on and off via a custom event. Approach the button while playing to activate it.)
- ボタンのクラス
BP_ButtonLight_Bulb_Basic
側のイベントOnComponentBeginOverlap
,OnComponentEndOverlap
でプレイヤー(ポーン)とのオーバーラップを検知して、ボタンの発光と電球のオンオフをしている BP_Light_Bulb_Basic
型の変数Target light
がpublic
になっていて、レベルに配置されたアクターBP_Generic_Button
の詳細パネルで対象のアクターが設定されていることで、それに対してカスタムイベントが呼び出される
1.2 Blueprint communication via actor casting
方法:対象アクターの変数を持っておき、カスタムイベントを呼び出す
説明文:「この例では、バッテリーを接続することで電球ブループリントのオンとオフが切り替わります。 電球はオーバーラップイベントを使用してバッテリーブループリントとの接触を検出し、それに応じてオン/オフになります。」 (In this example, a lightbulb Blueprint is toggled on and off by connecting a battery. The lightbulb uses an overlap event to detect contact with the battery Bluerpint and turns on/off accordingly.)
BP_Button_Battery
クラスがオーバーラップを検知して、BP_Battery
型の変数Target battery
に設定されたアクターにMove up/down
カスタムイベントを送り、上下移動させる- バッテリーが移動したことにより、電球
BP_Light_Bulb_Battery_Powered
側でオーバーラップを検知したら、自分のToggle Light
カスタムイベントを呼び出し、マテリアルの色とライトのIntensity
を変更する BP_Battery
のElectricity value
変数を見て明るさを決めている
1.3 Blueprint communication via actor casting to child Blueprint
方法:対象アクターの変数を持っておき、カスタムイベントを呼び出す
説明文:「これらの電球ブループリントは、異なる種類のバッテリーが接続することでオン/オフになります。 各バッテリーは同じ親ブループリントから派生していますが、異なるエネルギー値を持っていてライトの明るさに影響を与えます。」 These lightbulb Blueprints are turned on/off by connecting different types of batteries. Each battery is derived from the same parent Blueprint, but has different energy values that affect the brightness of the light.
- 1.2と同じだけど、3種類のバッテリーでそれぞれライトの明るさが変わる
BP_Battery
を親に持つBP_Battery_Small_Child
とBP_Battery_Big_Child
がそれぞれ指定されている- タイトルが “casting to child Blueprint” となっているが別に
Small_Child
やBig_Child
にキャストしているわけではなさそう
- タイトルが “casting to child Blueprint” となっているが別に
- バッテリーのパワーやメッシュの変更だけだったら
BP_Battery
に変数が用意されていてレベルのアクターの変数の設定で対応できると思うんだけど、わざわざ子クラスを作るのはなにか意味があるんだろうか?
1.4 Communicating with all actors of a specific class
方法:レベルに存在する特定クラスのアクターすべてにカスタムイベントを呼び出す
説明文:「この電球ブループリントたちはすべて、1つのボタンでオンまたはオフになります。 ボタンブループリントは、電球クラスのすべてのインスタンスを検索し、それぞれのインスタンスで「Toggle light」カスタム イベントを呼び出します。」 (This collection of lightbulb Blueprints are all turned on and off by one button. The button Blueprint finds all instances of the lightbulb class and calls the “Toggle light” custom event in each of them.)
- ボタンのクラス
BP_Button_Light_Bulb_Pulse
でGet All Actors Of Class
ノードを呼び出して、レベルに存在するすべてのBP_Light_Bulb_Pulse
型のインスタンスを列挙して操作対象にする- 複数の対象に対して
ForEachLoop
→Cast To
→個別にカスタムイベント呼び出し - 後の3.1のように(カスタムイベントとブループリントインターフェースという違いはあるが)、ループせずに一括対象にもできる模様
- 複数の対象に対して
- クラス
BP_Light_Bulb_Pulse
のカスタムイベントToggle light
で処理 - 電球の明るさの時間変化はタイムラインで行っている
2.1 Using an Event Dispatcher function to call an event in the Level Blueprint
方法:イベントディスパッチャーの呼び出しをレベルブループリント側で処理する
説明文:「これはイベントディスパッチャー機能を介して電球ブループリントのオンとオフを切り替えるボタンブループリントの例です。 このボタンはイベントディスパッチャーを呼び出し、レベルブループリントでイベントを起動してライトのオンとオフを切り替えます。」 (This is an example of a button Blueprint toggling a lightbulb Blueprint on and off via an Event Dispatcher function. The button calls the Event Dispatcher, which fires the event in the Level Blueprint to toggle the light on or off.)
- ボタンのクラス
BP_Button_Dispatch
でオーバーラップを検知してButton toggled
イベントディスパッチャーを呼び出す - レベルブループリントのイベントグラフに
Button toggled
を受け取るノードが設定されていて、対象の電球BP_Light_Bulb_Basic2
のToggle Light
カスタムイベントを呼び出して制御する - イベントディスパッチャーの
Variable Type
がMulticast Delegate
になっていて(固定されている)、レベルブループリントのイベントグラフに直接ノードが追加できている- 対象のアクターがレベルに配置されてるから?レベルのブループリントのイベントグラフから直接設定できる。レベルブループリントの
BeginPlay
でバインドする、といったことをする必要はない。
- 対象のアクターがレベルに配置されてるから?レベルのブループリントのイベントグラフから直接設定できる。レベルブループリントの
- この場合、レベルがお互いの関係を知っていて関連付けている
2.2 Binding an Event Dispatcher function to a custom event
方法:イベントディスパッチャーにバインドして、呼び出しを受け取る
説明文:「この例では同じボタンブループリントが回転アニメーションを開始および停止します。 この場合、回転ブループリントは、レベルブループリントを使用する代わりに、ボタンのイベントディスパッチャー機能を内部でカスタムイベントにバインドします。」 (In this example, the same button Blueprint starts and stops a rotating animation. In this case, the rotating Blueprint binds the button’s Event Dispatcher function to a custom event internally, instead of using the Level Blueprint.)
- 2.1と同じ
BP_Button_Dispatch
クラスだけど、電球(BP_Spinning_Loop_Dispatch
)側がBeginPlay
イベントでイベントディスパッチャーにカスタムイベントをバインドしている - この場合、電球側がボタン側を知っていて関連付けている
2.3 Binding an Event Dispatcher to a custom event on spawn
方法:イベントディスパッチャーにバインドして、呼び出しを受け取る
説明文:「このボタンを押すと爆弾のブループリントが生成されます。 このボタンは爆弾ブループリントが爆発したことを通知するディスパッチイベントを受信するまで、1回だけ押すことができます。」 (This button will spawn a bomb Blueprint when pressed. The button can only be pressed once, until it received a Dispatch Event notifying it that the bomb Blueprint has exploded.)
- ボタンは
BP_Button_Dispatch_Bomb
で、オーバーラップで自分のActivate
カスタムイベントを呼び出して爆弾をスポーンする。 - スポーンした爆弾(
BP_Bomb
)のイベントディスパッチャーBomb Exploded
にカスタムイベントをバインドして爆発終了を検知する。爆発するまでの間は2つ目は作られないようにする(Button Enabled
変数で管理)。 - イベントディスパッチャーのバインドのやり方自体は2.2と特に変わらない。
3.1 Basic communication using Blueprint Interface function)
方法:アクター配列変数に対してブループリントインターフェースの関数を呼び出す
説明文:「この例ではブループリントボタンはブループリントインターフェースメッセージを介してさまざまなブループリントの配列をアクティブにします。 各ブループリントは異なるクラスですが、同じブループリントインターフェース イベントを使用しているため、最初に各クラスにキャストする必要がなく、単一の関数ですべてをアクティブ化することができます。」 (In this example, a button Blueprint activates an array of different Blueprints via a Blueprint Interface message. Although each Blueprint is a different class, the fact that they employ the same Blueprint Interface Event makes it possible to activate them all with a single function, without the need to cast to each class first.)
- ボタン
BP_Button_Interface
にActor
配列型の変数Target Blueprints
があり、オーバーラップでBPI_Player_Interactions
ブループリントインターフェース(以下BPインターフェース)のPushed Button
関数を呼び出すActor
配列をForEachLoop
ノードでループしてCast To
とかせずに、直接与えられる模様- イベントグラフで右クリック>「Pushed Button」で選択できる
- インターフェースを実装しないアクタークラスの場合は無視されるっぽい
Target Blueprints
変数に設定されている3つのBPクラスBP_Light_Bulb_Interface
,BP_LED_Inteface
,BP_Spinning_Logo
はどれもBPI_Player_Interactions
を実装している- BPクラスがインターフェースを実装しているかどうかは、「⚙️Class Settings」をクリック>Interfaces>Implemented Interfaces に登録されていることを調べる。またMy Blueprint>INTERFACES に所定のインターフェースの関数があることを確認する。
3.2 Communication using a Blueprint Interface function
方法:オーバーラップしたアクターが特定のBPインターフェースを持っていたら呼び出す
説明文:「この例ではブループリントボタンは、BPインターフェースメッセージを介してさまざまなブループリントの配列をアクティブにします。 各ブループリントは異なるクラスですが、同じBPインターフェースイベントを使用しているため、最初に各クラスにキャストする必要がなく、単一の関数ですべてをアクティブ化することができます。」 (In this example, a button Blueprint activates an array of different Blueprints via a Blueprint Interface Message Although each Blueprint is a different class, the fact that they employ the same Blueprint Interface Event makes it possible to activate them all with a single function, without the need to cast to each class first.)
- 今までのサンプルと違いオーバーラップで電球がオンオフされるんではなく、オーバーラップでテキスト表示され、対象のレバーをマウス操作で電球がオンオフされる
- ポーン
MyCharacter_BP_Comms
でマウス左クリック時にGet closest interactive actor
関数でオーバーラップしているアクターの中からDoes Implement Interface
ノードでBPI_Player_Interfactions
を探し、水平距離が一番近いものをActor To interact With
変数に格納 Tick
イベントでinteracting
だったらBPI_Player_Interactions
のGrab Interact
関数を呼び出し、対象の各クラスで処理される(そっちの処理はあまりよく理解できなかった…)- 内容的には3.1 との違いがわからず、
Pushed button
に比べてGrab Interact
は引数や戻り値がある、という程度?
3.3 Communication using a Blueprint Interface function
方法:オーバーラップしたアクターが特定のBPインターフェースを持っていたら呼び出す
説明文:「この例では発射物の衝突を処理するためのBPインターフェースメッセージの使用を示します。 発射体ブループリントは衝突時に球体ブループリント上のインターフェース関数を呼び出し、各球体はインターフェースを介して渡された情報に対して異なる反応を示します。」 (This example demonstrates a Blueprint Interface Message use for handling projectile collisions. The projectile Blueprints call an Interface function on the sphere Blueprints when they hit, and each sphere responds differently to the information passed through the Interface.)
- 近くに来るとマウス左で火、マウス右で水を撃てるようになり、3種類の球に当たるとそれぞれ異なる反応をする
- 範囲かどうかはレベルに配置された
TriggerBox
とのオーバーラップをレベルブループリントのイベントグラフで取得してポーン(MyCharacter_BP_Comms
)のPowers Enabled
変数を書き換える
- 範囲かどうかはレベルに配置された
MyCharacter_BP_Comms
でマウスクリック時にShoot fireball
またはShoot water
カスタムイベントで、SpawnActor
ノードでBP_Projectile_Fire
またはBP_Projectile_Water
を生成- どちらも
ActorBeginOverlap
でオーバーラップしたアクターに対してBPI_Elemental_Projectiles
インターフェースのElemental Damage
関数にパラメータHeat
とWater
を渡して呼び出す - 3つの球はそれぞれ
BP_Metal_Sphere
,BP_WoodSphere
,BP_Ice_Sphere
クラスで、Elemental Damage
インターフェース関数を実装、パラメータに従って変数を変更し、Tick
イベントでマテリアルのパラメータを設定して火や水の影響を表示に反映させている
まとめ
- ブループリント間でやり取りするには カスタムイベント、 イベントディスパッチャー、 BPインターフェース の3通り
- 実際には他にも 関数呼び出し や変数参照・変更もあるっちゃある
- 各方法の特徴
- カスタムイベント:呼び出し元が呼び出し先のことを知っている(依存関係)
- イベントディスパッチャー:呼び出し元が呼び出し先のクラスを判定して処理を分ける、ということをしなくて済む
- 呼び出し元と呼び出し先が直接は無関係でいられて、バインドするやつが双方に依存する
- バインドは不特定多数で可能
- BPインターフェース:呼び出し元と呼び出し先がそれぞれBPインターフェースに依存するが、お互いは直接は独立
- インターフェース(や関数呼び出し)はイベントと違って戻り値を受け取れる、という違いがある
- 関数の場合
Delay
ノードなどの時間経過を含むノードは使えない。インターフェースの場合も戻り値がある場合は使えない?っぽい。戻り値がない場合には歯車が黄色になってイベントグラフ上に置かれる?
- 所感
- 配列に対して一括でカスタムイベントやBPインターフェースの呼び出し、またアクターに対してキャストせずに呼び出せることを知った
- 部屋がコンストラクションスクリプトで作られていてサイズなどを変更すれば対応できてすごいんだけど、 メッシュの構築などをノードで組むのは大変そう…