最初に
多少の使用方法に注意すべき点はあるものの、色々と使い道がありそうな機能でしたので
この機会に紹介したいと思います。
環境
Windows 11
UE 5.5.4
PropertyBagとは
InstancedStructなどが含まれている、StructUtilsプラグインの機能の一つです。
この機能はパラメーターを好きな型かつ名前で追加、変更、管理することができます
例:StateTreeのParameter
2025/05/08時点で既にStructUtilsプラグインはエンジンに組み込まれており、
PropertyBagはDeformerやChooserなど様々なコンテンツで幅広く使われています
使い方
1. 宣言
FInstancedPropertyBagを型とした変数を宣言します
UPROERTY()
FInstancedPropertyBag Bag;
ちなみに、エディタ側で値だけ編集を許可したい場合は
以下の様にmeta を設定することでUI上での編集を制限することが可能です。
UPROERTY(meta = FixedLayout)
FInstancedPropertyBag Bag;
下がFixedLayout指定したものですが、
プロパティの変更が出来なくなっているのが分かります
2. パラメーターの追加
エディタの場合
上に貼られている、StateTreeの例を参照ください。
※ちなみに、ランタイム中の操作に関してはBP用の関数がありません
この理由に関しては後述する注意点を参照してください。
コードの場合
プロパティの名前と型を指定してAddPropertyするだけです、とても簡単です。
static const FName PropertyName1(TEXT("Distance"));
static const FName PropertyName2(TEXT("Num"));
Bag.AddProperties({
{ PropertyName1, EPropertyBagPropertyType::Float },
{ PropertyName2, EPropertyBagPropertyType::Int32 }
});
3. パラメーターの中身の取得、設定
エディタの場合
PropertyBagはBPにおけるサポートはされていません
コードの場合
追加したパラメーターの名前と型に応じた関数を使用します。
// 値の取得.
Bag.GetValueInt32(PropertyName2);
// 値の設定.
Bag.SetValueInt32(PropertyName2, 10);
注意点
PropertyBagを使う上で、注意しなければいけないポイントがあります。
それはランタイム中にパラメーターの追加、削除を行うのは厳禁な点です
これに関してはPropertyBagの構成に理由があります。
以下簡単なFInstancedPropertyBagの構成
Instanced Structについて
簡単にいうとUEのリフレクション機能を利用して、
- 構造体の型(
UScriptStruct
) - 中身のメモリ
を持つことで異なる構造体を同じ型(FInstancedStruct
)で共通して扱うことができる構造体です。
※イメージし辛い方はヒストリアさんの使い方記事を参照頂くと分かりやすいかもしれません
UPropertyBagの生成とメモリ確保
FInstancedPropertyBag
では、上記Instanced Structで使用する構造体の型(UPropertyBag
)を
AddPropertyされたプロパティの名前や型のタイプなどをもとにハッシュ値を生成して、
それぞれ別のものとしてUPropertyBagのインスタンスを生成します。
つまり、
ランタイム中にAddPropertyをすると、UPropertyBagをその場で生成してしまいます
(詳細が知りたい方はUPropertyBag::GetOrCreateFromDescs
関数をご参照ください)
便利な動的型としてランタイム中に好きなもの詰めよ~!
とかすると呼び出しの度にメモリ確保されます。
ループで一個ずつAddPropertyとか追加される度に別の型扱いなので
全部その場でメモリ確保されます、地獄です。
UPropertyBagの使いまわし
ここで、プロパティが異なると、それぞれ別のUPropertyBagになるといいましたが
逆にプロパティの名前や型など中身が同じ構成ならば
既に生成されているUPropertyBagのインスタンスが使いまわされるため、動的なメモリ確保は行われません。
そのためアセット内に定義したInstancedBagの受け渡しなどは基本的に問題ありません。
最後に
ランタイム中の注意点だけ覚えておけば、アセットごとに動的な要素を持ちたい場合など、
色んな所で活用できる可能性がある機能思います。
もし、何か間違えている場合はご連絡いただけますと幸いです。