UE4+C++开发-(七十二)-UUMGManager、UMyGameInstance、PlayerController怎么调用?

要调用 
UUMGManager
 中带有 “输入模式设置” 的 UI 加载功能,核心是先获取 
UUMGManager
 实例
(通常挂载在 
UMyGameInstance
 中,确保全局可访问),再调用 
LoadAndShowWidget
 接口。以下是完整的调用流程,覆盖 C++ 代码调用 和 蓝图调用 两种场景,同时包含常见扩展需求(如指定输入模式、隐藏 UI 恢复输入)。

一、前提:确保 UUMGManager 实例全局可访问

首先需要在 
UMyGameInstance
 中存储 
UUMGManager
 实例(全局单例),这样任何地方都能通过 
GameInstance
 获取管理器。如果之前未配置,需先补充以下步骤:

1. 修改 UMyGameInstance.h(声明管理器变量)

cpp

运行



#pragma once
 
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "UMGManager.h" // 包含 UUMGManager 头文件
#include "MyGameInstance.generated.h"
 
UCLASS()
class PROJECT_API UMyGameInstance : public UGameInstance
{
	GENERATED_BODY()
 
public:
	// 游戏启动时初始化 UUMGManager
	virtual void Init() override;
 
	// 获取 UUMGManager 实例(全局访问接口)
	UFUNCTION(BlueprintCallable, Category = "UI Management") // 支持蓝图调用
	UUMGManager* GetUMGManager() const { return UMGManagerInstance; }
 
	// (可选)存储当前 PlayerController,供管理器 fallback 使用
	TWeakObjectPtr<APlayerController> CurrentPC;
 
private:
	// UUMGManager 实例(全局唯一)
	UPROPERTY()
	UUMGManager* UMGManagerInstance;
};

2. 修改 UMyGameInstance.cpp(初始化管理器)

cpp

运行



#include "MyGameInstance.h"
#include "UMGManager.h"
#include "GameFramework/PlayerController.h"
 
void UMyGameInstance::Init()
{
	Super::Init();
 
	// 创建 UUMGManager 实例
	UMGManagerInstance = NewObject<UUMGManager>();
	if (UMGManagerInstance)
	{
		UE_LOG(LogTemp, Log, TEXT("UMyGameInstance: UUMGManager 初始化成功"));
	}
	else
	{
		UE_LOG(LogTemp, Error, TEXT("UMyGameInstance: UUMGManager 创建失败"));
	}
}

3. 绑定默认 PlayerController(可选,确保管理器有默认 PC)

在 
PlayerController
 的 
BeginPlay
 中,将自身赋值给 
MyGameInstance
 的 
CurrentPC
,供管理器 fallback 使用:

cpp

运行



#include "PlayerController.h"
#include "MyGameInstance.h"
 
void APlayerController::BeginPlay()
{
	Super::BeginPlay();
 
	// 将当前 PC 绑定到 GameInstance
	if (UMyGameInstance* GI = Cast<UMyGameInstance>(GetGameInstance()))
	{
		GI->CurrentPC = this;
		// (可选)初始化 UUMGManager 的默认 PC
		if (UUMGManager* UIManager = GI->GetUMGManager())
		{
			UIManager->Initialize(this);
		}
	}
}

二、C++ 代码调用(核心场景)

在任何需要加载 UI 的地方(如 
PlayerController

GameMode

Actor
),通过 
GameInstance
 获取 
UUMGManager
 实例,再调用 
LoadAndShowWidget
。以下是 3 个典型场景示例:

场景 1:在 PlayerController 中加载 “主菜单 UI”(纯 UI 交互,隐藏角色控制)

cpp

运行



#include "PlayerController.h"
#include "MyGameInstance.h"
#include "UMGManager.h"
 
// 示例:按 ESC 键加载主菜单
void APlayerController::SetupInputComponent()
{
	Super::SetupInputComponent();
 
	// 绑定 ESC 键输入事件
	InputComponent->BindAction("OpenMainMenu", IE_Pressed, this, &APlayerController::OnOpenMainMenu);
}
 
void APlayerController::OnOpenMainMenu()
{
	// 1. 获取 GameInstance 和 UUMGManager 实例
	UMyGameInstance* GI = Cast<UMyGameInstance>(GetGameInstance());
	if (!GI) return;
 
	UUMGManager* UIManager = GI->GetUMGManager();
	if (!UIManager)
	{
		UE_LOG(LogTemp, Error, TEXT("OnOpenMainMenu: UUMGManager 实例为空"));
		return;
	}
 
	// 2. 定义 UI 路径(从 Content Browser 右键蓝图 → Copy Reference 获取)
	FString MainMenuPath = "/Game/UI/WBP_MainMenu.WBP_MainMenu";
 
	// 3. 调用 LoadAndShowWidget 加载 UI(自动设置输入模式为“仅 UI”+显示鼠标)
	UUserWidget* MainMenuWidget = UIManager->LoadAndShowWidget(MainMenuPath, this); // 传入当前 PC
 
	// 4. (可选)检查加载结果,处理异常
	if (!MainMenuWidget)
	{
		UE_LOG(LogTemp, Error, TEXT("OnOpenMainMenu: 主菜单加载失败(路径:%s)"), *MainMenuPath);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("OnOpenMainMenu: 主菜单加载成功"));
	}
}

场景 2:在 GameMode 中加载 “全局加载界面”(跨关卡持久化)

cpp

运行



#include "GameMode.h"
#include "MyGameInstance.h"
#include "UMGManager.h"
#include "GameFramework/PlayerController.h"
 
void AGameMode::BeginPlay()
{
	Super::BeginPlay();
 
	// 1. 获取 GameInstance 和 UUMGManager
	UMyGameInstance* GI = Cast<UMyGameInstance>(GetGameInstance());
	if (!GI || !GI->GetUMGManager()) return;
 
	UUMGManager* UIManager = GI->GetUMGManager();
 
	// 2. 获取默认 PlayerController(从 GameInstance 中获取,避免空指针)
	APlayerController* DefaultPC = GI->CurrentPC.Get();
	if (!DefaultPC) return;
 
	// 3. 加载全局加载界面(无需传入 PC,管理器会用默认 PC)
	FString LoadingUIPath = "/Game/UI/WBP_Loading.WBP_Loading";
	UIManager->LoadAndShowWidget(LoadingUIPath); // 第二个参数省略,使用默认 PC
}

场景 3:隐藏 UI 并恢复输入模式(如关闭主菜单)

当关闭 UI 时,需调用之前新增的 
HideWidget
 函数,恢复 “游戏 + UI” 输入模式(让玩家重新控制角色):

cpp

运行



// 在 PlayerController 中添加“关闭主菜单”函数
void APlayerController::OnCloseMainMenu()
{
	UMyGameInstance* GI = Cast<UMyGameInstance>(GetGameInstance());
	if (!GI || !GI->GetUMGManager()) return;
 
	UUMGManager* UIManager = GI->GetUMGManager();
	FString MainMenuPath = "/Game/UI/WBP_MainMenu.WBP_MainMenu";
 
	// 调用 HideWidget,传入 true 表示恢复输入模式
	UIManager->HideWidget(MainMenuPath, true); 
}

三、蓝图调用(给蓝图开发者使用)

如果需要在蓝图中调用 
UUMGManager
,需先确保 
UMyGameInstance
 和 
UUMGManager
 的关键函数添加了 
UFUNCTION(BlueprintCallable)
 宏(之前已配置)。以下是蓝图调用步骤:

1. 获取 UMyGameInstance 实例

在任何蓝图中(如 
PlayerController
 蓝图、
Actor
 蓝图),通过 “获取游戏实例” 节点,转换为 
MyGameInstance
 类型:

蓝图节点路径:
蓝图库 → 游戏实例 → 获取游戏实例
右键 “获取游戏实例” 节点的输出端 → 转换为 MyGameInstance

2. 获取 UUMGManager 实例

调用 
MyGameInstance
 的 “GetUMGManager” 函数(之前声明的蓝图可调用接口),获取管理器实例:

从 
MyGameInstance
 节点的输出端,拖拽出连线 → 搜索 “Get UMG Manager”

3. 调用 LoadAndShowWidget 加载 UI

从 
UUMGManager
 节点的输出端,拖拽出连线 → 搜索 “Load And Show Widget”(需确保 
LoadAndShowWidget
 函数添加了 
UFUNCTION(BlueprintCallable)
,若之前未加,需补充到 
UMGManager.h
 中):

cpp

运行



// 在 UMGManager.h 的 LoadAndShowWidget 声明中添加蓝图宏
UFUNCTION(BlueprintCallable, Category = "UI Management", meta = (DisplayName = "Load and Show UI"))
UUserWidget* LoadAndShowWidget(const FString& WidgetPath, APlayerController* InPC = nullptr);

输入参数:

Widget Path
:填写 UI 蓝图的完整路径(如 
/Game/UI/WBP_MainMenu.WBP_MainMenu
);
In PC
(可选):传入当前 
PlayerController
(如蓝图的 
Self
 节点,若为 
PlayerController
 蓝图)。

4. 蓝图调用示例(关闭 UI 恢复输入)

同理,调用 
UUMGManager
 的 “Hide Widget” 函数(需先给 
HideWidget
 添加 
UFUNCTION(BlueprintCallable)
):

cpp

运行



// 在 UMGManager.h 的 HideWidget 声明中添加蓝图宏
UFUNCTION(BlueprintCallable, Category = "UI Management", meta = (DisplayName = "Hide UI and Restore Input"))
void HideWidget(const FString& WidgetPath, bool bRestoreGameInput = true);

蓝图节点:从 
UUMGManager
 拖拽 → 搜索 “Hide UI and Restore Input”,传入 UI 路径和 
bRestoreGameInput = true

四、调用注意事项

UI 路径必须正确

路径从 
Content Browser
 右键蓝图 → Copy Reference 获取,确保包含完整的 
/Game/
 前缀(如 
/Game/UI/WBP_MainMenu.WBP_MainMenu
),避免手动拼写错误。若路径错误,
LoadAndShowWidget
 会返回 
nullptr
,并在 Output Log 中输出错误日志(搜索 
LogUMGManager
 可查看)。

PlayerController 必须有效

加载 UI 时,确保传入的 
InPC
 或管理器的 
DefaultPC
 非空(否则 UI 无法挂载到视口,也无法设置输入模式)。若在 
BeginPlay
 中调用,需确保 
PlayerController
 已初始化(如延迟 0.1 秒调用,避免关卡加载时 PC 未创建)。

输入模式冲突处理

若同时加载多个 UI(如主菜单 + 弹窗),只有最后加载的 UI 会获取输入焦点。建议通过 “弹窗队列” 管理(在 
UUMGManager
 中扩展),避免多个 UI 争抢输入。退出游戏时,需手动隐藏所有 UI 并恢复输入模式(可在 
MyGameInstance
 的 
Shutdown
 函数中调用 
UIManager->HideAllWidgets(true)
)。

通过以上步骤,无论在 C++ 还是蓝图中,都能稳定调用 
UUMGManager
 加载 UI 并设置输入模式,实现 “UI 交互” 与 “角色控制” 的无缝切换。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
万事顺遂如意的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容