Featured image of post [UE5] 入力ピンに接続した変数を読み書きする BP 関数を作成する方法 (BP で作成編) (Set By-Ref Var / Pass-by-Reference)

[UE5] 入力ピンに接続した変数を読み書きする BP 関数を作成する方法 (BP で作成編) (Set By-Ref Var / Pass-by-Reference)

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) になっていることが原因です。

値渡しの場合、関数が実行されると

  1. 変数 Int Var の『値』が、入力ピン Arg にコピーされる
  2. Set Integer (by ref) Node によって、Arg がインクリメントされる

という処理が行われます。

この場合、インクリメント処理の対象はあくまでも Arg となります。Int Var は『過去に値のコピー元になった変数』でしかなく、インクリメント処理とは無関係というわけです。

実際、Arg 自体は正しくインクリメントされていることが確認できます。

入力ピンに接続した変数がインクリメントされるようにするには、入力ピン Arg を『参照渡し』にする必要があります。

入力ピンを参照渡しにするには、関数の開始 Node を選択した状態で、Details PanelInput《該当の入力ピン》Pass-by-Reference にチェックを入れます。

Pass-by-Reference の項目が見当たらない場合は、折り畳まれている可能性があります。入力ピンの名前入力欄の左にある三角形をクリックして展開してください。

参照渡しにすると、ピンの形が丸から菱形になります。よく見ると Set By-Ref Var Node の Target も菱形のピンになっていますが、これも参照渡しのピンです。

参照渡しにすることで、関数が実行されたときに

  1. 変数 Int Var の『参照』が、入力ピン Arg に渡される
    • 「入力ピン Arg が、変数 Int Var を『参照』するようになる」と考えても OK
  2. 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^)/<おわり

参考