說明
學習一下如何將Widget藍圖與C++連線起來,將處理邏輯寫在C++中
基礎
在藍圖中,我們顯示Widget是透過一個Actor或者PlayerController,甚至關卡藍圖,利用Create Widget以及 AddToViewPort使得Widget顯示在螢幕上的
所以在C++中也是一樣,一般來說由於Actor的銷燬比如角色死亡,會導致其所有處理邏輯從記憶體中清除掉。所以將這個功能寫在PlayerController類裡。
現在為了演示,直接建立了一個Actor類和一個UserWidget類。
Actor類
其主要作用就是顯示這個UMG介面,在.h檔案中需要一個UserWidget類的指標,用來儲存Create出來的物件。相當於上圖中的那個變數
然後還需要接受一個類,一般透過TSubClassOf宣告,然後在引擎中選擇由UserWidget類建立好的藍圖類。相當於上圖中CreateWidget模組的Class
//.h
public:
UPROPERTY()
class UXDebugMenuWidget* XDebugMenu;
UPROPERTY(EditAnywhere, Category = "Debug")
TSubclassOf<class UUserWidget> DebugMenuWdgClass;
在.cpp檔案中就主要來實現上圖中的邏輯
//.cpp
//Create Widget
XDebugMenu = CreateWidget<UXDebugMenuWidget>(GetWorld(), DebugMenuWdgClass);
if (XDebugMenu)
{
XDebugMenu->AddToViewport();
}
CreateWidget函式
在原始碼中其為一個函式模板,
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;
}
可以看到有兩個資訊
- 該函式只能建立UserWidget 對於UWidget需要其他函式
- OwingObject的型別只能是UWidget UWidgetTree APlayerController UGameInstance UWorld其中的一種,其他的型別無法呼叫該函式
所以當在Actor呼叫該函式生成Widget的時候,可以利用GetWorld()來得到UWorld類的引數,如果在PlayerController類中直接使用this指標即可
UserWidget類
參考
該類主要是處理UMG在藍圖中的邏輯。需要注意到點就是每個控制元件的宣告是有嚴格的要求的,以Button控制元件為例
UPROPERTY(meta = (BindWidget))
class UButton* Button_Tab1;
- UPROPERTY(meta = (BindWidget))
BindWidget是一組專門用來繫結Button這些控制元件的列舉值中的一個UE官方文件 - 變數名稱:C++中控制元件的名稱必須和藍圖中一樣
- 用BindWidget標記過的 widget 在 C++ 建構函式中為空,它們稍後在生命週期中被初始化。如果您需要進行類似建構函式的設定,請使用該NativeConstruct()函式。
- 對於按鈕響應,可以呼叫官方設定好的委託函式廣播即可OnClicked.AddDynamic(this,&Func);
使用HUD
使用HUD可以對一個GameMode設定使用一種UMG顯示
GameMode是控制整個遊戲的規則,相當於一種最高許可權,可以設定玩家的控制器型別,預設角色型別,HUD型別等等。
當我們將將Widget放在HUD裡面是,我們就可以透過GameMode來控制一些數值的顯示,實際上是透過PlayerController來更改HUD的
可以將HUD理解為多個Widget的集合,我們將在HUD類裡實現在Actor類中的建立Widget的操作。程式碼都是一樣的,只不過OwingObject的型別我們需要修改為PlayerController,因為對於HUD類來說沒有GetWorld物件,但其受到每個玩家控制器的控制,具有GetOwningPlayerController()函式來獲取PlayerController。
然後就可以在PlayerController類裡面使用HUD類物件呼叫HUD中的方法實現UMG的顯示了。