UE4 中通過單例類實現全局數據管理
前言
單例模式(Singleton Pattern)是最簡單的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。
一、前期準備
Unreal Engine 4.25.4
Visual Studio 2019
新建空白關卡和對應的用戶控件。如何新建關卡可以參考以下視頻
新關卡一片黑?初學者必知的UE4新建關卡時的一些設置【虛幻引擎】。
控件 UI 的擺放如下圖所示,一個藍色按鈕和一個紅色按鈕,下面對應是藍色方和紅色方的比分。

然后修改關卡藍圖,將 UMG 添加到視口。

最后啟動運行關卡,預期能看到以下畫面。

二、C++ 代碼
新建 C++ 類,注意需要打開 顯示所有類,繼承自 Object 父類,并將生成的類命名為 Singleton,如下圖所示。


編輯源碼如下,需要注意的是由于反射機制, ue4 中的構造函數沒辦法轉為私有。
// Singleton.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "HAL/ThreadingBase.h"
#include "Singleton.generated.h"
/**
*
*/
UCLASS(BlueprintType, Blueprintable)
class SINGLETONOBJECT_API USingleton : public UObject
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable) // 藍圖可調用
static USingleton* GetSingletonObjectIns();
UFUNCTION(BlueprintCallable)
void InitializeObject(); // 初始化
UFUNCTION(BlueprintCallable)
void AddBlueScore();
UFUNCTION(BlueprintCallable)
int GetBlueScore();
UFUNCTION(BlueprintCallable)
void AddRedScore();
UFUNCTION(BlueprintCallable)
int GetRedScore();
private:
static FCriticalSection Mutex; // 鎖
static USingleton* SingletonInstance;
int BlueScore;
int RedScore;
};
// Singleton.cpp
#include "Singleton.h"
USingleton* USingleton::GetSingletonObjectIns()
{
FScopeLock ScopeLock(&Mutex);
if (SingletonInstance == nullptr)
{
SingletonInstance = NewObject<USingleton>();
SingletonInstance->InitializeObject();
}
return SingletonInstance;
}
void USingleton::InitializeObject()
{
this->BlueScore = 0;
this->RedScore = 0;
}
void USingleton::AddBlueScore()
{
++this->BlueScore;
}
int USingleton::GetBlueScore()
{
return this->BlueScore;
}
void USingleton::AddRedScore()
{
++this->RedScore;
}
int USingleton::GetRedScore()
{
return this->RedScore;
}
實現單例類后,我們還需要繼承實現 GameInstance,這是必要的一步,因為 GameInstance 的生命周期貫穿游戲始終,否則單例類變量會在關卡切換是被系統銷毀回收。以下演示了如何新建一個 GameInstance,并且將單例類作為其的私有屬性成員。


// MyGameInstance.h
#pragma once
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "Singleton.h"
#include "MyGameInstance.generated.h"
/**
*
*/
UCLASS()
class SINGLETONOBJECT_API UMyGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
UMyGameInstance();
UFUNCTION()
void StartGameInstance();
private:
USingleton* GlobalGameData;
};
// MyGameInstance.cpp
#include "MyGameInstance.h"
FCriticalSection USingleton::Mutex;
USingleton* USingleton::SingletonInstance = nullptr;
UMyGameInstance::UMyGameInstance()
{
GlobalGameData = USingleton::GetSingletonObjectIns();
}
void UMyGameInstance::StartGameInstance()
{
Super::StartGameInstance();
}
三、藍圖引用單例類
編寫完成單例類后,具體該如何調用呢?
有兩種方式,一種是 C++ 代碼調用,另一種是藍圖調用。
C++ 調用很簡單,一行代碼即可。
USingleton* SIngletonRef = USingleton::GetSingletonObjectIns();
接下來展示如何通過外部藍圖調用,在空間藍圖中編寫邏輯如下。


編寫完成后,保存并編譯,接下來啟動關卡,預期效果如下圖所示。每點擊一次藍色按鈕,藍色比分加一;每點擊一次紅色按鈕,紅色比分加一。

浙公網安備 33010602011771號