マクロライブラリでブループリントを見やすくしてみよう!

UE4

マクロライブラリって何?

マクロライブラリは、色々なブループリントから呼び出す処理をマクロとしてまとめておく機能ですが、説明を読むだけでは関数ライブラリとの違いがよく理解できません。

そんな謎多きマクロライブラリの活用方法はいくつかのサイトやブログで紹介されています。(記事の最後にリンクをまとめてあります)

この記事では、ブループリントの視認性向上という点で、マクロライブラリのメリットを紹介させていただきます!

マクロライブラリの視覚的強み

実行ピンの出力を複数設定できる

マクロは実行ピンの出力を複数設定できるため、処理の分岐判定をマクロ内で完結することができるようになります。

簡単な例として、Get関数の結果をIsValidチェックする手順を、下図のように簡略化してノード数を減らすことができます。

ちなみに、オブジェクト型のメンバ変数を取得する場合は「検証済みゲットに変換」という機能が用意されているので便利です。

他にはロード処理などで、ロード完了を待ってから出力されるピンと、ロード開始したらすぐ出力されるピンを用意することもできます。

実行ピンを複数設定できる魅了を知ってしまうといろいろな機能を内包したくなりますが、やりすぎは禁物です。後述しますがマクロはコンパイル時に展開される仕様のため、複雑な処理を内部に持たせるのは避けた方がよさそうです。

なんでも処理してくれる神マクロに注意

コンパクトノードタイトルを設定できる

コンパクトノードタイトルを設定することで、ノードの形を特集な形状に変えることができます。

こちらのブログで紹介されている活用法によって、主に定数の視認性を向上することができます。
マクロは悪? いえ、善です。(Blueprintに限る) – SEGA TECH Blog

上の場合は引数の文字列が見辛いのと、文字列や数値の意味するものがぱっと見だとわからない

ノードにカラーを設定できる

ノードに好きな色を設定できるので、特定のカテゴリごとに色分けすることで視認性があがります。

ブループリントのグラフは膨大になりがちなので、遠目で見たときに色で何の処理か判断できるのは非常にありがたいです。

関数ライブラリだと全て水色のノードで表示されるため、処理を探すときに関数名をいちいち読んだり、コメントで目立たせたりして余計な神経を使ってしまいます。

事例紹介

これまで紹介したマクロ活用術を使用しない場合と、使用した場合の比較です。

 

どうでしょうか?下の方が見やすく感じないでしょうか!?

大して変わらん!という方は、下記のMy色ルールを読んだうえで見直してみてください。

  • 赤ノード … プレイヤーステートを変更する
  • 緑ノード … プレイヤーの透明度を変更する
  • 紫ノード … ビューターゲットを変更する

余計に見辛いわ!という方は、もうこれ以上ありませんのでウィンドウをそっと閉じてください。。。

マクロライブラリを使用する際の注意点

アセット参照数に気を付ける

マクロライブラリに限らず、他の多くのブループリントから参照されるアセットは、依存関係に気を付ける必要があります。

こちらはヒストリアさんのブログにて詳しく解説されています。

不必要なアセットが依存して含まれてしまうと、ゲーム中にアクターを生成する際、芋ずる式にアセットがロードされてしまい、実際には読み込む必要がないアセットまでもが読み込まれて無駄にメモリを圧迫したり、ロードに無駄な時間がかかってしまいます。なので、極力依存関係が発生しないように作るか、もし依存関係が発生してしまう場合には、ライブラリを分けた方がよいです。

[UE4] 関数ライブラリとマクロライブラリの上手な活用|株式会社ヒストリア

解決策としては、1つのマクロライブラリに多くの機能を持たせるのではなく、関連するカテゴリごとにアセットを分けるようにします。

マクロはコンパイル時に展開される

もう一つマクロで注意すべきこととして、関数と違ってマクロはコンパイル時に展開されるということです。


上図はあくまでイメージですが、実際にゲームをプレイする時には、内部的にはこのように展開されているのだと理解することは重要です。

この問題点としては、複雑な処理が含まれるマクロや、マクロの中でさらにマクロを使用していた場合などは、展開後のノード数がえらいことになるのと、
そのマクロを仮に数十か所のブループリントから使用していた場合、そのすべての箇所で展開されるため、実行時のノード数が膨大になるということです。

これについてもヒストリアさんのブログにて解説されています。

ブループリントコンパイルが走ると、内部的にはマクロの中身が展開されてそのブループリントの中身は実は膨大なノードの量になってしまっていた、なんて事が起きかねません。マクロの中で別のマクロを使っていて、さらにその中でも別のマクロを…となるともはや実際のノード数は誰も把握していないなんて状況になるかもしれません。そんなブループリントが書かれているアクターをレベルに大量に配置してしまったら、やはりパフォーマンスは落ちてしまいます。

[UE4] 関数ライブラリとマクロライブラリの上手な活用|株式会社ヒストリア

この解決策としては、私の場合、マクロと同名の関数ライブラリを用意し、実装はそちらに記述するようにしています。

マクロライブラリは関数ライブラリのラッパー(関数ライブラリを呼び出すだけの存在)として実装することで、コンパイル時に展開すると関数ライブラリを呼び出しているだけのノードが残ります。

もちろんマクロによっては関数ライブラリを呼び出すだけでは済まないものもありますので、数ノードに展開されることはありますが、極力実装は関数ライブラリに逃がすようにしています。

GCのコストはどうなのよ?

ブループリントでマクロを作成するとUPropertyが生成され、GC(ガベージコレクション)の対象になります。このためマクロを多用するとGCの検索コストが上がってしまい、ロード/アンロード時などでヒッチ(ひきつり)が起きる問題があります。

このデメリットにより、これまでは一般的にマクロを多用せず関数を使用することが推奨されていました。

UE4におけるLoadingとGCのProfilingと最適化手法

この件について、UE4.25にて大きな変更がありました。

UProperty型がFProperty型となり、GCの対象外になりました。この変更により、マクロを多用するデメリットが大きく解消されたはずです!(ちゃんと検証してなくてスミマセン!)

この変更は4.25からですので、プロジェクトを4.25にアップデートする予定がない場合は注意してください。

このやり方の面倒な点

さて、いい話には裏がありまして、この活用術には面倒な点があります。

それを説明するには、まずマクロライブラリの以下の特徴を理解する必要があります。

1.マクロライブラリが使用できる関数は親クラスが使用できる関数のみ

そもそもマクロライブラリは、作成時にどのクラスを親として作成するかを指定します。作成したマクロライブラリは、親クラスの機能を使用することができます。

逆に言うと、指定した親クラスが使えない関数はマクロライブラリも使うことができません。

例えばGetPlayerCharacter関数やGetPlayerController関数は、Actor型を親クラスに指定してマクロライブラリを作成した場合は使うことができますが、全ての親であるObject型を親クラスに指定した場合は使用することができません。

2.マクロライブラリを呼び出せるのは継承したクラスからのみ

ブループリントがマクロライブラリのマクロ呼び出すことができるのは、自分と同じ親クラスを指定して作成されたマクロライブラリのみです。

Actor型が親クラスのマクロライブラリは、Actor型を継承したブループリントは使用できますが、UserWidget型を継承したウィジェットブループリントからは呼び出すことができません。

以上を踏まえたうえでの問題点

例えばGetPlayerCharacterマクロを様々なブループリントから使用したいと考えた場合、Object型を親としてマクロライブラリを作成したいところですが、マクロ内部でGetPlayerCharacter関数を使用するには、Actor型やUserWidget型を親クラスとしてマクロライブラリを作成する必要があります。

関数ライブラリであればGetPlayerCharacter関数を一つ実装すればよかったのを、マクロでは各親ごとに作成する必要があるということになります。

つまり、Object型の子であるActor、ActorComponent、GameInstace、GameMode、UserWidgetなどを継承したマクロライブラリを作成し、それぞれにGetPlayerCharacterマクロを実装する必要があります。

いくつかのアセットは内容が全く同じものがある

改善案

マクロはコンパイル時に展開されるの項目で述べたように、マクロライブラリの中身を極力シンプルに作っておくことで、同じマクロを親ごとに用意する際のコピペ作業はそこまで苦行ではありません。

考えようによっては…?

ライブラリ側の視点で考えると、ゲームに必要な機能を関数ライブラリで実装した場合、どのブループリントからもアクセス出来ることになり、好き放題出来てしまいます。

マクロライブラリの場合、親ごとに必要な機能だけを公開してブループリントの権限を制御できると捉えることもできます。

まとめ

今回はマクロライブラリでブループリントの視認性を向上する活用術を紹介しました。

ブループリントの視認性が上がることで、作業効率が上がり、バグも減らすことができます。そういう意味でマクロライブラリは非常に有用だと思います。

しかし最後に述べたようにマクロライブラリを多用することには手間もかかりますので、是非ご自身のやり方でマクロライブラリを活用してみてください!

参考