はじめに
お仕事で本件について調べたので、自分用メモも兼ねてご共有
といっても…ほぼ以下の記事のUserWidget版だけだったりします(素晴らしい記事をありがとうございます!)
[UE4] C++で動的にアクターを生成(スポーン)する方法で一番実用的だった方法
【UE4】同期的なアセットのロード方法とデメリット
検証環境:UE4.25.3
C++でアセットパスからUserWidgetClassを生成する方法
Widgetを作成するCreate Widget
を使うためには下図のノードにおけるClass
ピン、具体的には生成したいWidgetのUserWidgetClass
を用意する必要があります。
いくつか方法がありますが、その中から使いやすい方法をご紹介。
LoadSynchronousを使う方法
#include "Blueprint/UserWidget.h"
FString path = "/Game/UMG_Test.UMG_Test_C";
TSubclassOf<class UUserWidget> WidgetClass = TSoftClassPtr<UUserWidget>(FSoftObjectPath(*Path)).LoadSynchronous();
LoadObjectを使う方法
#include "Blueprint/UserWidget.h"
FString path = "/Game/UMG_Test.UMG_Test";
TSubclassOf<class UUserWidget> WidgetClass;
UBlueprint* BP = LoadObject<UBlueprint>(NULL, *Path);
if (BP != nullptr)
{
WidgetClass = BP->GeneratedClass;
}
どちらも有効ですが、ソフトリファレンスであるTSoftClassPtr
を使うLoadSynchronous
の方が非同期ロード対応やその他の管理が楽になるのでオススメです。
C++で指定のUserWidgetをCreateWidgetする方法
CreateWidget
をC++で実行する場合は
template <typename WidgetT = UUserWidget, typename OwnerT = UObject>
WidgetT* CreateWidget(OwnerT* OwningObject, TSubclassOf<UUserWidget> UserWidgetClass = WidgetT::StaticClass(), FName WidgetName = NAME_None)
{
static_assert(TIsDerivedFrom<WidgetT, UUserWidget>::IsDerived, "CreateWidget can only be used to create UserWidget instances. If creating a UWidget, use WidgetTree::ConstructWidget.");
static_assert(TIsDerivedFrom<OwnerT, UWidget>::IsDerived
|| TIsDerivedFrom<OwnerT, UWidgetTree>::IsDerived
|| TIsDerivedFrom<OwnerT, APlayerController>::IsDerived
|| TIsDerivedFrom<OwnerT, UGameInstance>::IsDerived
|| TIsDerivedFrom<OwnerT, UWorld>::IsDerived, "The given OwningObject is not of a supported type for use with CreateWidget.");
SCOPE_CYCLE_COUNTER(STAT_CreateWidget);
if (OwningObject)
{
return Cast<WidgetT>(UUserWidget::CreateWidgetInstance(*OwningObject, UserWidgetClass, WidgetName));
}
return nullptr;
}
または、
UCLASS(meta=(ScriptName="WidgetLibrary"))
class UMG_API UWidgetBlueprintLibrary : public UBlueprintFunctionLibrary
{
GENERATED_UCLASS_BODY()
public:
/** Creates a widget */
UFUNCTION(BlueprintCallable, BlueprintCosmetic, meta=( WorldContext="WorldContextObject", DisplayName="Create Widget", BlueprintInternalUseOnly="true" ), Category="Widget")
static class UUserWidget* Create(UObject* WorldContextObject, TSubclassOf<class UUserWidget> WidgetType, APlayerController* OwningPlayer);
を呼び出すことになります。
前者は少しややこしいコードに見えますが、実際に使う上で注意すべき点はOwningObject
にはUWidget
, UWidgetTree
, APlayerControllr
, UGameInstance
, UWorld
のいずれかを渡す必要があるという点です。ですので、
TSubclassOf<class UUserWidget> WidgetClass;
WidgetClass = TSoftClassPtr<UUserWidget>(FSoftObjectPath(*Path)).LoadSynchronous();
UUserWidget* UserWidget = CreateWidget<UUserWidget>(GetWorld(), WidgetClass);
といった感じで使うことができます。
サクッとした内容でしたが少しでもご参考になれば幸いです。