「Unreal Engine (UE) Advent Calendar 2022 その3」1日目の記事となります。
はじめに
自作ゲームの方で長くUMGを触ってきましたが、理解度が深まって来たので情報を共有します。今回はC++からUMGのウィジェットやアニメーションを取得する方法について解説です。
※検証バージョン UE4.27.2(Developmentパッケージでも動作確認)
※将来的にUE5でも検証予定で差異があれば追記します
※間違えてたらコメント欄で教えていただけると嬉しいです
- はじめに
- ウィジェットの取得
- アニメーションの取得
- 基本は~~Optionalを使うのを推奨?
- UPROPERTYを使用しないでWidgetを取得する方法
- まとめ
- おまけ:ウィジェットの取得(BindWidgetOptional)にTransientを付与してみたら
- 参考サイト様
ウィジェットの取得
下記のようにUPROPERTYを定義します。すると変数名と同名のウィジェットがバインドされます。
UPROPERTY(meta = (BindWidget))
UMyTextBlock* WidgetName = nullptr;
アニメーションの取得
UPROPERTY(Transient, meta = (BindWidgetAnim))
UWidgetAnimation* AnimationName = nullptr;
使い方はBindWidgetと似ています。変数名と同名のアニメーションを取得します。また、Animationの場合はTransientを付けないとエラーが出ます。こちらもOptional版があります。
基本は~~Optionalを使うのを推奨?
処理としては共通だけど片方のウィジェットには文字を表示したいが、もう片方には表示させたくない等はよくある話かと思います。
この場合、片方のUMGには該当のテキストウィジェットを削除しますが、Optionalではない場合BPコンパイルエラーとなってしまいます。
上記のようなエラーを避けるためにもOptionalで実装する方がよいかと思われます。
UPROPERTYを使用しないでWidgetを取得する方法
実はUPROPERTYを使用せずともWidgetは取得できます。自分はもっぱらこっちのやり方をやっていたり。
void UTestUserWidget::NativeConstruct() { UTextBlock* _txtTitle = Cast<UTextBlock>(GetWidgetFromName(TEXT("txtTitle"))); Super::NativeConstruct(); }
このやり方はNativeConstructの負荷が少し上がりますが、UPROPERTYを使わないといった利点もあります。
あとSuper::NativeConstruct()の前にやるのを推奨です。後にやってしまうとBP側のEventConstructが先に走るので、その際に変数を参照するような作りにするとnullptrアクセスしてしまいます。
おまけ:ウィジェットの取得(BindWidgetOptional)にTransientを付与してみたら
参考文献ではウィジェット取得時のUPROPERTYにTransientが付いてないのですがTransientを付けていてもパッケージで動作するようです。
調べてみましたがUserWidgetを生成時(UUserWidget::Initialize内部)にウィジェットと同名のプロパティ検索をかけ、そこでプロパティとバインドしているのでTransientが付いていても問題ないようです。
でも、そこで検索かけると負荷がかかるのでは?と思いました。この辺りはどれが正解なのかピンと来ていませんが一例として残しておきます。