UnityユーザーのためのUEブループリント入門
コードとビジュアル両方のスクリプトを比較してゲームエンジンを学びます

9. 関数、メソッド

Unityのメソッドは独自のメソッドを記述することで、類似したソースコードをまとめたり、ソースコードの可読性を高めることができます。
Unreal Engineの関数は、EventGraph上にノードをつなげていくと、どうしても可読性が低くなるため、関数をつくることで、処理をまとめることができます。関数のほかにも、イベント、マクロ、インターフェースがあり、その違いについても見てみましょう。
  • 関数(メソッド)
  • 引数のある関数
  • 返り値(戻り値)のある関数
  • 関数内にあるデータを返した場合
  • [UEのみ]純粋関数
  • [UEのみ]関数、イベント、マクロ、インターフェースとの違い

9. メソッド

9.1 メソッド

メソッド名は自分の好きな名前をつけてもよいですが、一部つけられない名前もあります。
以下のスクリプトはaaa()メソッドはどこからも呼ばれていません。
void Start(){
}
void Update(){
}
void aaa(){
    Debug.Log("aaaが呼ばれた");
}
メソッドの呼び出し
Startメソッドで呼ぶようにします。
処理の流れは、Unity側からStartメソッドが呼ばれてから、Startメソッド内で記述したaaaメソッドが呼ばれます。
void Start(){
    aaa();
}
void Update(){
}
void aaa(){
    Debug.Log("aaaが呼ばれた");
}
メソッドの処理順
以下の一連の処理の流れは1フレーム内で行われます。
  • メソッドが呼び出される(呼び出し元) → 直ちに処理を実行する
  • 処理が終わる → 呼び出し元に戻る
void Start(){
    Debug.Log("Start1");
    aaa();
    Debug.Log("Start2");
}
void Update(){
}
void aaa(){
    Debug.Log("aaaが呼ばれた");
}
メソッドは何度でも呼べる
メソッドは何度でも呼べます。
void Start(){
    aaa();
    aaa();
    aaa();
}
void Update(){
}
void aaa(){
    Debug.Log("aaaが呼ばれた");
}
void Start(){
    int b = 0;
    aaa();
    aaa();
    aaa();
    Debug.Log(b);
}
void Update(){
}
void aaa(){
    int b = 0;
    ++b;
    Debug.Log("aaaが呼ばれた");
}

9.2 引数のあるメソッド

void Start(){
    //定義した変数と同じ型のデータを入れます
    aaa(1);
}
void Update(){
}
//変数を定義します
//aaa(1)からデータが渡されます
void aaa(int b){ //引数
    Debug.Log(b);
}
void Start(){
    //型があっていればいろんなデータが送れます。
    aaa(1);
    aaa(2);
    aaa(3);
}
void Update(){
}
void aaa(int b){ 
    Debug.Log(b);
}
変数のスコープに気をつけた引数の扱い方
同じ名前の変数でスコープが被っている場合は、スコープが狭い方が優勢されます。
void Start(){
    int b = 0;
    aaa(b);
    aaa(b);
    aaa(b);
    Debug.Log(b);
}
void Update(){
}
void aaa(int b){ 
    ++b;
}
スコープが狭い方が優先されます。
int b = 0;
void Start(){
    aaa(b);
    aaa(b);
    aaa(b);
    Debug.Log(b);
}
void Update(){
}
void aaa(int b){ 
    ++b;
}
複数の引数
,で区切ることで複数の引数を定義できます。
void Start(){
    //,で区切って引数と同じようにデータをいれる
    //複数データを渡せる
    aaa(1,2,3);
}
void Update(){
}
void aaa(int a, int b, int c){ 
    Debug.Log(a + b + c);
}

9.3 返り値(戻り値)のあるメソッド

値を返すメソッドを作成します。
void Start(){
    //返ってきたデータを代入
    int b = aaa(1,2,3);
    Debug.Log(b);
}
void Update(){
}
//返すデータの型
int aaa(int a, int b, int c){ 
    //returnは定義した型と同じ型のデータを返す
    return a + b + c;
}
returnについて
return以下の命令は処理されません。
int aaa(int a, int b, int c){ 
    return a + b + c;
    Debug.Log("aaa");
}

9.4 メソッド内にあるデータを返した場合

メソッドで値を返していますが、スコープ内の変数が優先されるのと、返した値を受け取っていないので変数bは0になります。
void Start(){
    int b = 0;
    aaa(b);
    aaa(b);
    aaa(b);
    Debug.Log(b);
}
void Update(){
}
void aaa(int b){ 
    return ++b;
}
メソッドから値を受けるには変数bに代入します。
void Start(){
    int b = 0;
    b = aaa(b);
    b = aaa(b);
    b = aaa(b);
    Debug.Log(b);
}
void Update(){
}
void aaa(int b){ 
    return ++b;
}

9. 関数

9.1 関数

関数(Function)の作り方は、ブループリントエディタの+Functionボタンを押して作成します。関数名は自分の好きな名前をつけることかできます。
関数の呼び出し
BeginPlayイベントノードで呼ぶようにします。
処理の流れは、BeginPlayイベントノードから実行ワイヤーで接続されたaaa関数が呼ばれます。
関数の処理順
関数の処理順は実行ワイヤーで繋がれた順に実行します。
関数は何度でも呼べる
関数は何度でも呼べます。
関数aaaはローカル変数を持つことができます。しかし既にレベル上で作成している関数名と重複した名前をつけることはできません。
bがグローバル変数ならばaaa関数を呼んだ分だけbにインクリメント加算されます。

9.2 引数のある関数

引数のある関数を作成するには、関数ノードの詳細パネルのInputsで引数を追加作成します。
Inputsの+New Parameterボタンを押します。
型を選択して名前を決めます。
Inputから得られた値を関数内で定義します。以下はPrint Stringノードに繋げて引数の値を表示しています。
BeginPlayイベントノードにaaa関数を実行ワイヤーで繋げ、引数の値を入力します。
変数のスコープに気をつけた引数の扱い方
UE BPでは関数別にローカル変数を持つことができないため、Unityのようにスコープに注意して記述する必要はありません。以下はUnityのスクリプトに準じてブループリントを記述します。
aaa関数を以下のように記述します。
三つ目のaaa関数の結果が変数bに反映されて出力されます。
変数bの値にインプットを値としてaaa関数に渡します。
aaa関数内でbの値がセットされた結果を引き継いで、変数bの値が加算されます。
複数の引数
データピンを追加することで複数の引数を定義できます。
a,b,cのInteger型の三つの引数を追加します。
三つの引数それぞれを加算した結果をPrint Stringノードで出力するaaa関数を作成します。
EventBeginイベントノードとaaa関数を実行ワイヤーで接続します。

9.3 返り値(戻り値)のある関数

UE BPでも値を返す関数を作成できます。
以下は関数ノードの詳細パネルのInputsで引数を追加しています。返り値のある関数を作る例になりまして、必ず作るものではありません。
返り値のある関数を作成するには、関数ノードの詳細パネルのOutputsで返り値を追加作成します。Outputsの+New Parameterボタンを押します。
型を選択して名前を決めます。
Outputsの+New Parameterを追加すると、Return Nodeノードが作成され、返り値が追加されます。
aaa関数の処理を追加します。
BeginPlayイベントノードとaaa関数を実行ワイヤーで接続して、aaa関数の返り値をPrint Stringノードに出力するようにします。
returnについて
unityとは異なり、Return Node以下に処理を追加することはできません。

9.4 関数内にあるデータを返した場合

「変数のスコープに気をつけた引数の扱い方」でも説明したとおり、UE BPではスコープという概念がなく、関数内で独自に変数を持たせることはできません。
以下の場合はインクリメントした値を変数bに反映することはできません。
以下のように変数bをセットすることで変数bに反映することができます。
以下の二つのブループリントは同じ結果を表示します。
横に長くなる場合はSequenceノードを使うことで整理できます。
関数のoutputデータピンを他の関数のinputデータピンに繋げることもできます。

9.5 [UEのみ]純粋関数

純粋関数になると、実行ワイヤーで追加することなく関数の処理結果をデータピンとして渡すことができます。さらに詳細パネルでConstにチェックすると絶対的な純粋化(pure化、またはpurify)になります。絶対的な純粋化は、外部から影響を受けることができない関数になります。
純粋関数に変換する方法は、ノードを右クリックして、Convert to pure castを選択します。

9.6 [UEのみ]関数、イベント、マクロ、インターフェースとの違い

各機能の詳しい説明は専門書にゆだねるとして、実行時間の短縮を図る立場として、その使用傾向としては以下のように分類されます。
  • イベント > 関数 > マクロ
  • インターフェース
ポイントとしては以下になります。
  • 戻り値が必要ないこと、Delayノードを多用するなら、なるべくイベントを使う
    • 戻り値を返すための時間が発生するため
  • それ以外は関数を使う
  • インターフェースは、Tickやキャストをなるべく避けるために使う
  • ブループリント内だけで整理したいときだけにマクロを使う
このような特徴があることから、Unityで言うところのvoidを使っていましたが、UE BPではイベントを多用することになります。
特徴 イベント 関数 マクロ インターフェース
入力ピン 1個 0~1個 0個以上 1個
出力ピン 1個 0~1個 0個以上 1個
引数 0個以上 0個以上 0個以上 0個以上
ローカル変数 あり なし あり あり
戻り値 なし 0個以上 0個以上 0個以上
アクセス指定子 public public protected private private public
オーバーライド 不可
ノードネットワークの合流等ノード制限 なし あり なし 実装方式による
引数のワイルドカード指定 不可 不可 可能 不可
🔗 参考リンク
GameProgrammar's Night ゲームプログラム系の覚え書き
UE4 イベント・関数・マクロ・インターフェイスの違いと使い分け
マクロの強みについて引用して簡単に補足しておきます。マクロは、呼び出しがそのクラス内に限定されているので、比較的自由度の高い処理を行わせることが可能です。関数では呼び出しが不可能な、Delay当の潜在ノードが配置できます。ForEachLoopノードもワイルドカードを用いて汎用性の高いロジックをマクロ化することでイベントグラフ内を整理することができます(引用 : 逆引きブループリントより)。マクロについてはこの後も登場することなく、特に詳しく解説しません。
🔗 参考リンク
Qiita
ブループリントで関数、マクロ、イベント、インタフェース(Unreal Engine 4.25)
🔗 参考リンク
Qiita
ブループリントのアクター関連の関数とイベント(Unreal Engine 4.25)