UE 5.1.1
(UE 4.8.3)
結論
以下の 2 点を押さえれば実装できます。
Set By-Ref Var
Node を使うことで、入力ピンに接続した変数への代入ができる- 関数の入力ピンの
Pass-by-Reference
のチェックをオンにすることで、入力ピンを参照形式にできる
実例
『入力ピンに接続した Integer
型変数をインクリメント (+ 1) する BP 関数』を作成してみます。
接続した変数に値を代入する処理を作成する
まずは、変数への代入処理について考えます。
代入先の変数が予め決まっている場合は、Set 《変数名》
Node を使うことで値の代入ができます。
しかし、今回は代入先を『入力ピンに接続した変数』にする必要があり、代入先が不定であるため、この Node を使って目的の処理を実装することはできません。
このような場合は、Set By-Ref Var
Node を使います。
Target
に接続した変数に対して、Value
の値が代入されます。
Integer
型変数 Int Var
をインクリメントしたい場合は、このように実装できます。
Set By-Ref Var
Node の名前が Set Integer (by ref)
に変化している点に注意してください。Target
もしくは Value
に接続した型に応じて、Node 名が Set 《型名》 (by ref)
に変化する仕組みになっています。
なお、変化後の名前で Node 検索をしても出てきません。こちらもご注意ください。
これで、『入力ピンに接続した変数をインクリメントする処理』はできました。
処理を関数化する
インクリメント処理を関数にまとめます。こんな感じでいいのかな……?
……と思って動作確認してみると、入力ピンに接続した変数がインクリメントされないという結果になりました 😱
これは、関数の入力ピン Arg
が『値渡し』 (Pass-by-Value) になっていることが原因です。
値渡しの場合、関数が実行されると
- 変数
Int Var
の『値』が、入力ピンArg
にコピーされる Set Integer (by ref)
Node によって、Arg
がインクリメントされる
という処理が行われます。
この場合、インクリメント処理の対象はあくまでも Arg
となります。Int Var
は『過去に値のコピー元になった変数』でしかなく、インクリメント処理とは無関係というわけです。
実際、Arg
自体は正しくインクリメントされていることが確認できます。
入力ピンに接続した変数がインクリメントされるようにするには、入力ピン Arg
を『参照渡し』にする必要があります。
入力ピンを参照渡しにするには、関数の開始 Node を選択した状態で、Details Panel
→ Input
→ 《該当の入力ピン》
→ Pass-by-Reference
にチェックを入れます。
Pass-by-Reference
の項目が見当たらない場合は、折り畳まれている可能性があります。入力ピンの名前入力欄の左にある三角形をクリックして展開してください。
参照渡しにすると、ピンの形が丸から菱形になります。よく見ると Set By-Ref Var
Node の Target
も菱形のピンになっていますが、これも参照渡しのピンです。
参照渡しにすることで、関数が実行されたときに
- 変数
Int Var
の『参照』が、入力ピンArg
に渡される- 「入力ピン
Arg
が、変数Int Var
を『参照』するようになる」と考えても OK
- 「入力ピン
Set Integer (by ref)
Node によって、Arg
を介してInt Var
がインクリメントされる
という処理が行われるようになります。
これで完成です。
余談 : Engine の IncrementInt
Node
今回は解説のためにインクリメント処理を行う BP 関数を作成しましたが、Unreal Engine にはデフォルトで IncrementInt
マクロが用意されているので、自分で作成する必要はありません。
この IncrementInt
マクロは UE 4.8 で実装されたのですが、当初は出力ピンが『出力ピンの値の利用時における入力変数の値 + 1』を返す実装になっていました。
より具体的に言うと、
IncrementInt
マクロの実行直後に出力ピンの値を利用すると、マクロ実行直前の変数の値 + 2 が返るIncrementInt
マクロで + 1 された値にさらに + 1 した値が返るため
IncrementInt
マクロの入力ピンに接続した変数の値を別の場所で変更すると、出力ピンが返す値が変わる- 出力ピンの値がキャッシュされておらず、出力ピンの値の利用時に再計算されるため
という挙動になっており、実用に足るものではありませんでした。
IncrementInt
はマクロで実装されているため、Node をダブルクリックすることで中身を見ることができます。UE 4.8.3 での中身はこのようになっていました。
現在では、出力ピンが『最後にマクロを実行した時点でのインクリメント後の値』を返す実装になっています。
この挙動は、マクロ内のローカル変数に結果の値をキャッシュすることで実現しているようです。
ちなみに DecrementInt
はもっと酷くて、実装当初は『ゼロを引く』という処理になっていたため、何もかも機能していませんでした 👹
テストはちゃんとしましょう……。
\(^o^)/<おわり
参考
- UE4 引数として関数へ渡した変数の中身を書き換える(リファレンス渡し)(Set By-Ref Var) 凛(kagring)のUE5/UE4とゲーム制作と雑記ブログ
- 関数のリファレンス渡しの変数に値をセットする方法 - Programming & Scripting / Blueprint - Epic Developer Community Forums
- UE4:BPマクロ/関数の入力でPass-by-Reference利用時の注意 - ヒマがあるならゲームつくってね
- [UE4] ちょっとだけ幸せになれるブループリント|株式会社ヒストリア
- 『Compact Node Title でコンパクトに!』の項にて、
+=
Node を作るために参照渡しの入力ピンを使用
- 『Compact Node Title でコンパクトに!』の項にて、
- 【UE4】Blueprintパラメーターの参照渡しについて【★★】 | キンアジのブログ
- 値渡しと参照渡しでパフォーマンスに差が出る事例についての解説