こんにちは、株式会社Leon Gameworksの遠藤です。
第2回では、前回の内容を踏まえた上で、「アセットのプロパティを設定・取得」する方法をツール作成の過程で解説していきます。
0:動作環境
本記事はUE5.3.2を基に執筆しており、エディターの言語は「英語」でスクリーンショットを撮影しております。
本記事で作成するツールのプロジェクト一式のデータは以下からダウンロードできます。
1:プロパティマトリクス
ツール制作の前に、UE5の標準機能である「プロパティマトリクス」について紹介しておきます。公式ドキュメントはこちら。

プロパティマトリクスでは、プロパティの確認や値の変更を一括で行えます。そのため、大抵のプロパティに関しては、Editor Utility に頼らなくてもプロパティマトリクスを活用することで一括操作することができます。
それを踏まえて、今回は、プロパティマトリクスではアクセスできないプロパティの設定・取得を行うツールを作成していきます。
2:メッシュのマテリアルスロットを操作するツールの作成
2-1:ツールの概要
Content Browser上で選択中のスタティックメッシュアセットのマテリアルスロットを表示し、ツール上で操作するEditor Utility Widget(以下、EUW)を作成します。

2-2:ツールのデザイン
まずは Editor Utilityアセットの作成やツールのデザインを行なっていきます。今回もEUWを基に作成します。

ルートウィジェットは[Vertical Box]を選択し、アセット名は「EUW_MaterialList」とします。

アセットを開き、以下のような階層構造にします。
特別な設定はしていませんが、[EditorUtilityButton]と[EditorUtilityScrollBox]の間に、パディングを「8.0」設定してスペースを作っています。

コンテンツブラウザに戻り、もう1つEUWを作成します。
こちらもルートウィジェットに[Vertical Box]を選択し、アセット名は「EUW_MaterialSlots」とします。ツールとしてはEUW_MaterialListを実行し、EUW_MaterialList内で取得したアセット情報をEUW_MaterialSlotsで表示します。

[EUW_MaterialSlots]を開き、以下のような階層構造にします。ブループリントでロジックを組んでいないので、まだ以下のような見た目にはなっていなくて問題ありません。

こちらは構造が少し複雑なので、まずはウィジェットの役割を解説します。
まず[Border]は、ウィジェット間の隙間を空けるために配置しています。画像の箇所でパディングや色の設定をしています。

[AssetThumbnailWidget]と[TextBlock]は、アセットのサムネイルとアセット名を表示しています。

[DetailsView]ウィジェットで、スタティックメッシュアセットから取得したマテリアルスロットの情報を表示しています。

2-3:ツールのロジック作成
ウィジェットについて確認できたところで、早速EUW_MaterialSlotsのグラフモードに移動して、ブループリントでロジックを組んでいきましょう。
前回は[Event Construct]ノードを使用しましたが、今回はデザインモードでプレビューも行いたいため、[Event Pre Construct]ノードを使用します。これらのイベントは、EUWの起動時だけではなく、様々なタイミングで実行されるため、一度のみ実行されるように[Do Once]ノードを使用します。
また、前回同様[Details View]ウィジェットの[Set Object]で自身を登録していきます。

次に、Name型の入力ピンを1つもったカスタムイベントを作成します。

[Set Object]の先に[Bind Event to On Property Changed]ノードを繋げます。[On Property Changed]イベントは、[Details View]で表示するプロパティが変更されたときに実行されるイベントです。

2種類の変数を用意します。
1つ目は、[Static Material]という構造体の配列です。この構造体は、内部的にマテリアルスロットの情報として使われています。
2つ目は、[Static Mesh]型の変数です。情報を取得するスタティックメッシュアセットを格納します。
また、画像のように「MaterialSlots」変数には、「Material Slots」というカテゴリを設定しておきます。

StaticMesh変数の[Details]から画像のように設定します。デフォルト値は、デザイナーモードでのプレビュー用に設定しています。

デザイナーモードに切り替えて、[TextBlock]、[AssetThumbnailWidget]、[DetailsView]の3つに対して[Details→Is Variable]にチェックし、変数化します。

ウィジェットも含め、5つの変数を用意します。

[DetailsView]の[Details→Category to Show]に「Material Slots」を指定します。

グラフモードに戻り、[Event Pre Construct]の末尾にアセット名とサムネイルを表示する処理を繋いでいきます。

コンパイルし、デザイナーモードで確認するとアセットのサムネイルと名前、MaterialSlots変数が表示されるようになりました。

まだEUW_MaterialSlotsに実装はしますが、いったんEUW_MaterialListの実装に移ります。
[EUW_MaterialList]を開き、グラフモードに切り替えます。[EditorUtilityButton]の[On Clicked]イベントをグラフに追加します。

前回は任意のフォルダのアセットを取得しましたが、今回はコンテンツブラウザで選択中のアセットを取得するように実装していきます。
Editor Utility で使用できる「選択中のアセットを取得するノード」はいくつかあります。

今回はスタティックメッシュアセットのみ取得したいので、[Get Selected Assets Of Class]を追加します。[Asset Class]ピンには[Static Mesh]を指定します。

取得したスタティックメッシュアセットをFor文で回します。ピンがObject型なのでStaticMeshでキャストします。

Static Meshごとに「EUW_MaterialSlots」を作成し、Scroll Boxの子ウィジェットとして追加します。

全体として画像のようになりました。

ここまでできたら一度実行してみましょう。「EUW_MaterialList」を実行し、スタティックメッシュアセットを選択した後にツールの[Check]ボタンを押すと、選択したアセットがリスト化されます。

次に、マテリアルスロットの情報が表示されるようにブループリントを組んでいきます。
「EUW_MaterialSlots」を開き、グラフモードに切り替えます。マテリアルスロットの情報を取得するために[Get Editor Property]というノードを使用します。

[Get Editor Property]は、オブジェクトのプロパティの中から[Property Name]で指定した名前のプロパティを取得できます。出力ピンの[Property Value]はワイルドカード型になっており、他の型のピンを繋いで明示的に型を指定する必要があります。

型がオブジェクトの場合は、画像のようにクラスの関数を繋ぐことで型を指定できます。

また、構造体の場合は、画像のように構造体のBreakノードなどを繋ぐことで取得できます。

もし取得するプロパティの型と繋いだピンの型が違う場合は、Output Logに以下のような警告が表示されます。警告文に正しい型も書いてありますので参考にしましょう。
Warning: Script Msg: Property 'StaticMaterials' (ArrayProperty) on '/Game/Props/SM_Chair.SM_Chair' (StaticMesh) tried to get to a property value of the incorrect type (StrProperty)
[Event Pre Construct]の末尾に[Get Editor Property]ノードを繋げます。[Property Name]には[StaticMaterials]を指定し、[Material Slots]の変数に格納します。

最後に[OnPropertyChanged]イベントに[Set Editor Property]を繋ぎます。

Set Editor Propertyは、オブジェクトのプロパティに値を代入できるノードです。Get Editor Propertyと同じように[Property Value]ピンはワイルドカード型になっていて、他のピンを繋いで明示的に型を指定します。
これでツールの完成です。グラフ全体は画像のようになりました。

それでは、実行してみましょう。マテリアルスロットの情報が表示され、編集すると即座にアセットに反映されます。

3:Set/Get Editor Propertyを用いたテクニック
「Set/Get Editor Property」は、オブジェクトの全てのプロパティにアクセスすることができます。
C++で定義されているプロパティは、UPROPERTYに「EditAnywhere」や「VisibleAnywhere」などの指定子が付いていると、エディタ上から確認・編集が可能ですが、これらの指定子が付いていないような、公開されていないプロパティなどにもアクセス可能です。
また、画像のように取得した[Object]型のプロパティからさらにプロパティを取得することもできます。

4:まとめ
今回はオブジェクトのプロパティの設定・取得方法について解説しました。
前回と今回はコンテンツブラウザ上のアセットに対して実行するツールを作成しましたが、第3回はレベル上のアクターに対して実行するツールを作成していきます。
本記事で作成したツールのプロジェクト一式のデータは、以下からダウンロードできます。

株式会社Leon Gameworks
●公式サイト
www.leon-game.co.jp
●X(Twitter)
@Leon_Gameworks

トンコツ(遠藤俊太)
●トンコツ開発ブログ
shuntaendo.hatenablog.com
●X(Twitter)
@tonkotsu3656
TEXT_トンコツ(Leon Gameworks)
EDIT_小村仁美 / Hitomi Komura(CGWORLD)