趣旨
プレイヤー(ThirdPersonCharacterとか)がゴール(TrigerBox とか)に入ったら、ゴール地点にあるテキスト(TextRendereActor とか)の文字を非同期に変えたい、みたいことをしようとする場合、
- プレイヤーがゴールに入った時のイベントを、ゴール側かプレイヤー側のアクターで拾う。
- そのイベントが発生したときに、ゴール地点にあるテキストにもイベントを伝える。
- テキストは自分の表示している文字列を変更する。
という処理が必要になる。つまり、あるアクターでイベントが発生したとき、そのアクターとは別のアクターのイベントを連動して呼び出す必要がある。その方法についてのメモ。
ちなみに、同期でよければ関数でもできる。
前提
- Windows 10 Home/Pro
- Unreal Engine 4.24
テンプレートは、みんな大好き Third Person を使用。Third Person テンプレートを使用したプロジェクトの生成については下記で書いたのでここでは省略。
方針
Third Person テンプレートで作ったプロジェクトの中に、衝突判定をするためのボックストリガーを置いて、その領域にプレイヤー(キャラクター)が入ったら、最初からサンプルの底面に置かれてる Third Person と書かれた TextRenderActor の文字を別の文字に変更する、というプログラムを書いてみる。
この、どまんなかの水色の文字のところを、GOALに変更するということ。ボックストリガーから外に出たら元の文字に戻す。
手順
ボックストリガーを置く
左側の「基本」の中にある「ボックストリガー」をメイン画面の中にドラッグドロップする。名前はデフォルトで TriggerBox になる。
位置と大きさを適当に調節する。キャラクタがこの領域に入ったら、テキストの文字が変わるようにするので、範囲に入ったことをわかりやすくするために、ボックストリガーは大きめにしといたほうがいいかも。
これで、画面上の物体の配置はおしまい。
イベントを送信する側(ボックストリガー)の Blueprint の編集
TriggerBox を選んで「ブループリント/スクリプトの追加」を押す。
パスはどこにしてもいい。とりあえずそのまま「ブループリントを作成」を押す(コンテンツのルートに置かれる)。名前は、何も入れなければ TriggerBox_Blueprint となる。
画面中央上あたりにある「イベントグラフ」というタブを押す。
こんな感じの画面が出る(はず)。
左側にある、マイブループリントと書かれたタブの一番下にある「イベントディスパッチャー」というところの右にある+を押す。名前は何でもいいけど、ここでは DarekaKitade にしてみる。
右側の「詳細」がこんな感じになっているので、「インスタンス編集可能」という項目にチェックを入れる。これ重要。これをやらないと、他のアクター(ブループリント)でイベントを参照することができない。
DarekaKitade をイベントグラフ内にドラッグドロップするとメニューが出るので「呼び出し」を選ぶ。
DarekaKitade ノードができるので、「イベント ActorBeginOverlap」とつなぐ。
これで、TriggerBox の領域の中に他のアクターが入ったら(ちょっとでもかすめたら)、DarekaKitade イベントが呼ばれるようになる。ただし、現時点では DarekaKitade イベントの中身が何も作られていないので、この状態でプログラムを実行して、キャラクターでボックストリガーの範囲に入ってみても何も起こらない。
左上の「コンパイル」のところに?マークが出ていると思うので、コンパイルボタンを押す。Blueprint の編集が終わって、メインのウィンドウに戻るとき、コンパイルのところに?が出ていたら必ず押しておく。おさないと、ブループリントの編集結果がメインのウィンドウに反映されなくて、以後の操作ができないことがある。
イベントがちゃんと発生しているかわかりやすくするために、PrintString ノードを追加してみた。追加方法は、イベントグラフ内で右クリックして PrintString と入力すると対応するノードが出てくるので、それをメニューから選ぶ。InString のところに「だれか来たで!」と入力しておくと、このイベントが発生したときに、画面左上に「だれか来たで!」と表示される。
こんな感じ。実行(Alt+P)する前に、コンパイルの?がないのを確認しておくこと。
イベントを受信する側(TextRenderActor)の Blueprint の編集
メインウィンドウに戻って、TextRenderActor を選ぶ。
右側にある「ブループリント/スクリプトの追加:を押す。
このウィンドウが出たらそのまま「ブループリントを作成」を押す。
するとこんな画面になる。名前はデフォルトで TextRenderActor_Blueprint となるはず。
イベントグラフのタブを選んで、イベントグラフを出しておく。
左側のマイブループリントの下のほうの「変数」の横の+を押して、EventOkutteKuruyatu という名前の変数を追加する。(自分のプログラムで変数を作るときは名前は何でもいい)
EventOkutteKuruyatu を選んだ状態で右を見ると、詳細のところに「変数の型」というプルダウンメニューがあるのでそれを押す。そして、検索欄に Trigger と入力する。すると、さっき編集した Trigger Box Blueprintが選択肢に出てくるので、それを選ぶ。
変数の型の下にある「インスタンス編集可能」にチェックを入れる。これ重要。これをしないと。この後の操作をしてもプログラムがうまく動かない。
ここで一度「コンパイル」を押してメインウィンドウに戻る。
イベントの送信元を選ぶ
ここまでの操作がうまくいっていれば、メインのウィンドウで TexRenderActor_Blueprint を選ぶと、詳細の下のほうに「デフォルト」という項目ができていて、その中に Event Okutte Kuruyatu という項目ができているはず。できていなかったら、コンパイルボタン押してないとか、インスタンス編集可能にチェックが入ってないとか、何か間違っているので手順を見直してみる。
プルダウンメニューを開くと、送信する側のアクターとして TriggerBox_Blueprint が選べるので、それを選ぶ。
このようになれば成功。再度 TexRenderActor_Blueprint を選んだ状態で、ブループリントを編集を押す。
ボックストリガーのイベントを受信できるようにする
TexRenderActor_Blueprint のイベントグラフを開いて、左側の「変数」の EventOkutteKuruyatu を選択すると、右側の「詳細」の下のほうに緑色の枠の中に白い+が書かれたボタンがたくさん並んでいる状態になっている(はず)。その一番上に、TriggerBox_Blueprint で追加した Dareka Kitade というイベントがある(はず)。このボタンをクリックする。
すると、こんな感じで Dareka Kitade イベントのノードがイベントグラフに追加できる。これで TriggerBox_Blueprint で発生した Dareka Kitade イベントが受信できるようになったので、あとは、ふつうにイベントの処理をするプログラムを書いていけばOK。
PrintString ノードをつなげると簡単にテストできる。
こんな感じにすると、TextRenderActor 側でイベントを受信したときに、左上に「イベント受信したで!」と表示される。
正常に実行されると、キャラクターを文字の前(のボックストリガーのあたり)に動かすと、左上にこんな感じで「イベント発生側で出力している文字列」と「イベント受信側で出力している文字列」が療法表示される。
そういえば表示文字を変えるんだった
PrintString で画面に文字を出すなら、アクター間でのイベントの送受信は必要ないよね…ということで、当初の目的に沿って、TextRederActor の文字を変更して、ちゃんと受信側で処理ができることも確認しておく。
イベントグラフ内で右クリックして SetText と入力すると、Set Text(TextRender) という選択肢が出るので、それを選ぶ。
あとは上の画面のような感じでグラフを作る。
- Text Render という青いノードは SetText を置いたら勝手に作られる。
- SetText でセットする文字列のデフォルト値がノードに入力できないので、String 型の変数(Textという名前)を作って、それを入力にしている。
- Text 変数のデフォルト値に何科文字を入れておく。ここでは Dareya!! と入れてある。何も入れないと、プレイヤーが範囲に入った瞬間、文字が消えることになる。
- Text 変数から SetText の Value につなぐと、自動で ToText という緑のノードが追加される(はず)。
正しくプログラムが欠けていれば、こんな感じで Third Person と床に書かれていた文字が変更される。
ちなみに、地面に表示する文字に日本語も文字列を指定すると化けてしまう(デフォルトのフォントが日本語に対応してないみたい)。
イベントでの値(パラメータ)の受け渡し
イベントに引数(パラメータ)がある場合は、送信側と受信側でそれぞれイベントにパラメータを追加する必要がある。
ここまでのプログラムを改良して、地面に表示される文字列をボックストリガー側からパラメータで指定できるようにしてみる。
TriggerBox_Blueprint のイベントグラフを開いて、イベントディスパッチャーの中の Darekakitade を選ぶ。右上の詳細の一番上のところに「インプット」という項目があるので、その右側にある+を押す。+を押そうとすると「New Parameter」と表示される。
名前を OkuruMoji として、その右側(型)は String を選ぶ。
これで「コンパイル:を押すと、すでに追加してある DarekaKitade ノードの下に「OkuruMoji」という項目ができるので、そこに何か文字を入力する。ここでは Haitta! としてみた。
範囲から出たときは、また Third Person に戻すために、範囲外に出た側の処理も追加しておく。イベントグラフで右クリックして ActorEnd と入力すると「イベント ActorEndOverlap」という項目が選べるので、それを探して選択する。
こんな感じでグラフを作る。
ActorEndOverlap は、他のアクターが範囲外に出たときに発生するイベントなので、このイベントの発生時に Third Person という文字列をパラメータにして Dareka Kitade イベントを発生させてやれば、底面に書かれた文字は元に戻るはず(きっと)。
これで TriggerBox の書き換えは終わったので、コンパイルしておく。
受信側の変更
受信する側の TextRenderActor_Blueprint のイベントグラフは、TriggerBox_Blueprint 側の変更が正しくできていて、コンパイルをちゃんと押していれば、DarekaKitade イベントに OkuruMoji パラメータが追加されているはず。
こんな感じに繋ぎ変えてみる。これで、イベントで送られてきた文字(OkuruMoji)が画面と底面と両方に表示されるようになる。
コンパイルしてから、メインウィンドウで実行(Alt + P)する。
入った時。
出たとき。
こんな感じで、イベントを受け取る側で、プログラム実行中に受け取るイベントを変更しないなら、この方法でアクター間の送受信を実現できる。
イベントをバインドする方法
送信側からイベントを受け取るとき、送信側のイベント名と別のイベント名を受信側で作って、イベント同士を関連づける(バインドする)ことができる。イベントの送信元を変更したい場合や、複数のイベントと関連付けたい場合に使ったりする。
以下、TextRenderActor 側でバインド、バインドする手順のみメモしておく。
TextRenderActor_Blueprint のイベントグラフで右クリックして Dareka と入力して、右上にある「状況に合わせた表示」のチェックを外す。すると「Dareka Kitade イベントをバインド」のメニューが出るのでそれを選ぶ。チェックを外さないと表示されなくて途方にくれることになる。
適当なイベントディスパッチャーを作る。ここでは DokujiKansuu というイベントディスパッチャを作った。
詳細で、パラメータ「UketoruMoji」を追加する。型は String にしておく。
DokujiKansuu をイベントノード内にドラッグドロップして、メニューから「イベント」を選ぶと、上のようになるはず。
図のようにつなぐ。ポイントは、BeginPlay イベントに「Dareka Kitade にイベントをバインド」を追加することと、「イベントをバインド」のノードを「DokujiKansuu」の赤いポチで結ぶことの二つ。この操作で、プログラムが実行された直後に、DarekaKitade (delagate) が DokujiKansuu イベントにバインド(関連付け)されて、以後は DarekaKitade が呼び出されるたびに、DokujiKansuu イベントも発生するようになる。
ターゲットの EventOkutteKuruyatu は、変数としてすでに追加されているものを使う。これを target につなげておかないと、TriggerBox からイベントが受け取れない。
実行させると、先に示した方法で実装した場合と全く同じ動作になる(はず)。
参考:関数を呼び出す
非同期でなくてよければ、関数でもできる。テキストを変更するくらいなら、関数でやっても(遅延とかあるわけじゃないので)ふつうは問題はおきないはず。
以下、このページの「ボックストリガーを置く」までやってあるとして、関数を使って Third Person の文字を変える方法をメモしておく。
TextRecderActor に文字を変更する関数を追加する
TextRecderActor にブループリントを追加する。ブループリント名はデフォルトで TextRecderActor_Blueprint になる。
イベントグラフのタブを押すと上のようになる。
左側の「マイブループリント」のタブの中にある「関数」の右の+を押して関数を追加する。名前はここでは MojiWoKaeru にしてみた。
右側の「詳細」のところの「インプット」の+を押して、引数を追加する。引数名は Moji として、型は String にする。この引数に渡された文字列を、TextRederActor の文字として設定するようにプログラムを書く。
最初に SetText (TextReder) を関数のグラフエディタ内に配置する。
あとはこんな感じにつなぐ。MojiWoKaeru の Moji と SetText の Value をつなごうとすると、自動で ToText というノードが間に作られる。TextRender は自動的に追加されるはず。
ここまでやったらコンパイルしておく。
TriggerBox から TextRenderActor の関数を呼び出す
メインウィンドウで TextRederActor を選んで、ブループリント/スクリプトを作成を押す。
ファイル名はデフォルトで TextRederActor_Blueprint になる。
変数を作る。名前は KansuYobidashiSaki とした。
変数の型は、呼び出し先の TextRenderActor_Blueprint にする。
「インスタンス編集可能」にチェックを入れる。
コンパイルして、メインウィンドウに戻る。
TriggerBox_Blueprint を選ぶと、下のほうに「デフォルト」KansuuYobidashiSaki という項目が追加されているので、プルダウンメニューから TextRenderActor_Blueprint を選ぶ。
TriggerBox_Blueprint のイベントグラフに戻って、変数の KansuuYobidashiSaki をグラフ内にドラッグドロップして、Get KansuuYobidashiSaki を選ぶ。
Kansuu Yobidashi Saki の青いノードのポチの先を引っ張り出すと、メニューが出るので Moji と入力する。すると、上のように TextRenderActor_Blueprint に作った関数の Moji Wo Kaeru が選べるので、それを選ぶ。
あとはこんな感じでつなぐ。
コンパイルして実行すると、キャラクターが TriggerBox に入ったときに文字が変わるようになる。
ActorEndOverlap イベントについてもグラフを書けば、出たときにも文字を変更できる。
こんな感じに書くと、
出た時も文字が変わる。
同期実行で問題ない場合(同期実行させたい)や、返り値が必要な場合は、イベントではなく関数を使う。非同期に実行させたい場合や、複数の処理を同時に実行させたい場合、呼び出す処理をプログラム実行中に変更したい(バインド先を変更したい)場合などはイベントを使う。
参考文献
- イベント ディスパッチャー(公式ドキュメント)
- Blueprintクラスから他のBlueprintクラスの関数を呼び出すために、EventDispatcherを使う方法
- UE4 ブループリントでイベントディスパッチャーを使う
一番下の記事が最も参考になりました。上の2つで残りの情報を補完しました。
注意
関数名や変数名を、わざと日本語っぽいのにしているのは、その名前を付けていることに意味はない(システムにその名前を要求されているわけではない)ことを示しているだけで、日本語っぽい名前にするのがいいという意味ではないので悪しからず。