Choose your operating system:
Windows
macOS
Linux
在本教程中,可学习使用虚幻示意图形(UMG)构建具有多屏幕和按钮的基本菜单系统。
1.设置UMG的模块依赖性
虚幻引擎4 ,建议先阅读 编程快速入门 tutorial 。本教程将假设您已熟悉项目的创建、向其中添加C++代码,以及编译代码。同时也会向 蓝图 公开函数和属性。如欲了解更多信息,可从 变量、定时器和事件 tutorial
-
将从新建项目开始:
-
点击新项目中的 游戏 分类,然后点击 下一步 。
-
选择一个空白模板并点击 下一步 。
-
确认启用了 C++ 、 台式机/主机 和 使用初学者内容包(With Starter Content) 设置。
-
将项目命名为"HowTo_UMG"。
虚幻运动图形(UMG) 的代码,因此需进入 Visual Studio
-
-
使用主编辑器界面上 文件 下拉菜单中的 打开Visual Studio 命令来获取项目代码。
-
UMG依赖于模块,因此需将此类模块添加至HowTo_UMG.Build.cs中。
在HowTo_UMG.Build.cs中,需将UMG添加到包含的公共模块列表中,并将Slate和SlateCore添加到包含的私有模块列表中。需对HowTo_UMG的构造函数首行进行如下修改:
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });
然后将以下行取消注释:
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
完整源代码提供如下,以便仔细核对代码。
设置UMG后,可在项目的自定义 游戏模式 中添加代码,以创建和显示游戏菜单。
半成品代码
HowTo_UMG.Build.cs
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class HowTo_UMG :ModuleRules
{
public HowTo_UMG(TargetInfo Target)
{
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });
//PrivateDependencyModuleNames.AddRange(new string[] { });
// 如使用Slate UI,则取消注释
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// 如使用在线功能,则取消注释
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// if ((Target.Platform == UnrealTargetPlatform.Win32) || (Target.Platform == UnrealTargetPlatform.Win64))
// {
// if (UEBuildConfiguration.bCompileSteamOSS == true)
// {
// DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam");
// }
// }
}
}
2.扩展游戏模式
-
创建的菜单将由 用户控件 组成。需编写函数以新建并显示用户控件,然后在游戏开始时调用该函数。同时还需追踪创建内容,以便之后进行删除。各项目已有自定义 游戏模式 类,可直接打开,其在HowToUMGGameMode.h中被定义。需将以下函数和属性添加到类的底部:
public: /** 移除当前菜单控件,并在指定类(如有)中新建控件。*/ UFUNCTION(BlueprintCallable, Category = "UMG Game") void ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass); protected: /** 游戏开始时调用。*/ virtual void BeginPlay() override; /** 游戏开始时,用作菜单的控件类。*/ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UMG Game") TSubclassOf<UUserWidget> StartingWidgetClass; /** 用作菜单的控件实例。*/ UPROPERTY() UUserWidget* CurrentWidget;
-
为在代码中使用用户控件,需在#include部分的顶部添加以下行:
#include "Blueprint/UserWidget.h"
-
现在开始处理HowTo_UMGGameMode.cpp,需填充声明的两个函数的主体。将从覆盖 BeginPlay() 开始:
void AHowTo_UMGGameMode::BeginPlay() { Super::BeginPlay(); ChangeMenuWidget(StartingWidgetClass); }
Super::BeginPlay
-
接下来,同样在HowTo_UMGGameMode.cpp中,需定义菜单间的变化。如视口中存在活跃的用户控件,需将其移除。然后可新建用户控件,并将其添加到视口中。
void AHowTo_UMGGameMode::ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass) { if (CurrentWidget != nullptr) { CurrentWidget->RemoveFromViewport(); CurrentWidget = nullptr; } if (NewWidgetClass != nullptr) { CurrentWidget = CreateWidget<UUserWidget>(GetWorld(), NewWidgetClass); if (CurrentWidget != nullptr) { CurrentWidget->AddToViewport(); } } }
虚幻引擎
-
最后,需要在 玩家控制器(Player Controller) 类上设置输入模式。为此,在项目中添加基于 玩家控制器 的新C++类。游戏开始时,只需在此类中调用一个额外函数,便能确保与UI元素进行交互。
在HowTo_UMGPlayerControlle.h中,将向该类添加以下覆盖:
public: virtual void BeginPlay() override;
在HowToUMGPlayerController.cpp中,将添加被覆盖的函数:
void AHowTo_UMGPlayerController::BeginPlay() { Super::BeginPlay(); SetInputMode(FInputModeGameAndUI()); }
代码框架已构建完毕,以创建和显示菜单并在无需要时将其删除。现在返回 虚幻编辑器 ,开始设计菜单资源吧!
成品代码
HowTo_UMG.Build.cs
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class HowTo_UMG :ModuleRules
{
public HowTo_UMG(TargetInfo Target)
{
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });
//PrivateDependencyModuleNames.AddRange(new string[] { });
// 如使用Slate UI,则取消注释
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// 如使用在线功能,则取消注释
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// if ((Target.Platform == UnrealTargetPlatform.Win32) || (Target.Platform == UnrealTargetPlatform.Win64))
// {
// if (UEBuildConfiguration.bCompileSteamOSS == true)
// {
// DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam");
// }
// }
}
}
HowTo_UMGGameMode.h
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Blueprint/UserWidget.h"
#include "GameFramework/GameModeBase.h"
#include "HowTo_UMGGameMode.generated.h"
/**
*
*/
UCLASS()
class HOWTO_UMG_API AHowTo_UMGGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
/** 移除当前菜单控件,并在指定类(如有)中新建控件。*/
UFUNCTION(BlueprintCallable, Category = "UMG Game")
void ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass);
protected:
/** 游戏开始时调用。*/
virtual void BeginPlay() override;
/** 游戏开始时,用作菜单的控件类。*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UMG Game")
TSubclassOf<UUserWidget> StartingWidgetClass;
/** 用作菜单的控件实例。*/
UPROPERTY()
UUserWidget* CurrentWidget;
};
HowTo_UMGGameMode.cpp
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#include "HowTo_UMG.h"
#include "HowTo_UMGGameMode.h"
void AHowTo_UMGGameMode::BeginPlay()
{
Super::BeginPlay();
ChangeMenuWidget(StartingWidgetClass);
}
void AHowTo_UMGGameMode::ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass)
{
if (CurrentWidget != nullptr)
{
CurrentWidget->RemoveFromViewport();
CurrentWidget = nullptr;
}
if (NewWidgetClass != nullptr)
{
CurrentWidget = CreateWidget<UUserWidget>(GetWorld(), NewWidgetClass);
if (CurrentWidget != nullptr)
{
CurrentWidget->AddToViewport();
}
}
}
HowTo_UMGPlayerController.h
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "GameFramework/PlayerController.h"
#include "HowTo_UMGPlayerController.generated.h"
/**
*
*/
UCLASS()
class HOWTO_UMG_API AHowTo_UMGPlayerController : public APlayerController
{
GENERATED_BODY()
public:
virtual void BeginPlay() override;
};
HowTo_UMGPlayerController.cpp
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#include "HowTo_UMG.h"
#include "HowTo_UMGPlayerController.h"
void AHowTo_UMGPlayerController::BeginPlay()
{
Super::BeginPlay();
SetInputMode(FInputModeGameAndUI());
}
3.创建菜单控件蓝图
-
在 虚幻编辑器 中,可按 编译 按钮构建新代码。利用此操作可将 用户控件 用作菜单。
-
现在创建被 游戏模式 用作菜单的用户控件。通过 内容浏览器 中的 新增(Add New) 按钮,即可完成此操作。 控件蓝图 类位于 用户界面 类别中。需创建两个控件,并分别命名为MainMenu和NewGameMenu。可主菜单开始游戏,同时拥有可进入新游戏菜单的选项。
-
双击刚刚创建的主菜单 控件 ,前往 蓝图设计器 ,可在其中创建菜单布局。
-
将 按钮 和 文本 从 控制板面板 的 常用 部分拖入 图表 。该按钮将被用于打开新游戏菜单。
-
创建正确布局的首部,便是调整按钮的位置和大小。应进行以下修改:
-
将大小设为 -200 x -200。
-
将位置设为(-200,-200)。
-
将其重命名为NewGameButton,以便之后将其与功能连接时进行识别。
-
-
由于未绘制一套按钮的自定义图像,因此可通过将文本块拖放到按钮上并进行以下修改,以标记按钮:
-
设置"新游戏"的文本显示。
-
将可见性改为"点击测试不可见"。此操作可防止文本块阻碍鼠标点击下方按钮。
-
将命名设为NewGameText。此并非必要步骤,而是好习惯。
-
-
接下来,将使用第二个按钮和文本块,创建"退出"功能。其设置方法与新游戏按钮和文本块的设置方法相同,但有以下变化。
-
将按钮命名设为QuitButton
-
将按钮的位置设为(-200,-400)
-
将文本块命名设为QuitText
-
-
完成后即可将 事件 添加到按钮,以便点击按钮时运行代码。通过在 细节面板 中找到并按下相应事件命名旁的+号,便能完成此操作。而现在, OnClicked 即是要使用的事件。同时创建NewGameButton和QuitButton控件的的该事件。
蓝图
-
对于名为 OnClicked(NewGameButton) 的事件,需:
-
连接 ChangeMenuWidget 节点,以使用之前添加到GameMode中的功能。
-
将 ChangeMenuWidget 节点上的 新控件类** 字段设为NewGameMenu资源。
-
-
对于名为 OnClicked(QuitButton) 的事件,需:
-
连接 Quit Game 节点。
-
构建主菜单后,可设置在关卡启动时立即加载主菜单的GameMode资源。
4.配置游戏模式
-
基于项目的 GameMode ,在 内容浏览器 中添加 蓝图类 .利用此操作,可将这两个类上的公开变量设为需要的值。为此,需:
-
在 内容浏览器 中点击的 添加 按钮。
-
选择 HowTo_UMGGameMode 作为父类。其将被列入 所有类(All Classes) 部分。
-
将得到的蓝图资源命名为MenuGameMode。
-
-
为使游戏光标出现在游戏中,需进行GameMode中的相同操作,创建 PlayerController 的蓝图。
-
在 内容浏览器 中再次点击 添加 按钮。
-
在 常用类(Common Classes) 部分选择 玩家控制器 。
-
将该蓝图命名为MenuPlayerController。
-
-
编辑MenuPlayerController。
-
勾选 显示鼠标光标(Show Mouse Cursor) 复选框。
-
-
编辑MenuGameMode。
-
须将 启动控件类(Starting Widget Class) 设为MainMenu资源,以便在游戏开始时打开菜单。
-
应将 默认Pawn类(Default Pawn Class) 设为 Pawn 而非 DefaultPawn ,玩家便不会在菜单中乱飞。
-
应将 玩家控制器类 设为创建的MenuPlayerController资源,以便在游戏中显示鼠标光标。
-
-
为使用蓝图,必返回 关卡编辑器 窗口,并通过 设置 按钮修改当前 关卡 的 场景设置 。
地图和模式 部分的 项目设置
-
将打开 场景设置面板 。其将默认与 细节面板 停靠,但也可将其移动到其他位置。需将 游戏模式覆盖(Game Mode Override) 字段设为MenuGameMode资源。
自定义GameMode资源现已在关卡上生效,并被配置以加载主菜单,同时使用显示鼠标光标的玩家控制器。如现在运行游戏,退出按钮将预期生效,使用新游戏按钮将进入空白菜单。将在下一步中设置新游戏菜单。
5.构建二级菜单
-
在 内容浏览器 中,找到并打开之前创建的NewGameMenu资源。该菜单将包含可输入命名的 文本框 、开始游戏的 按钮 (输入命名前无法按下),及可返回主菜单的按钮。
-
为创建命名输入框,需将文本框(而非 文本块 )拖入布局。
-
应按以下值配置文本框:
-
将命名改为NameTextEntry
-
位置(325,200)。此操作可在文本框左侧预留空间,以放置文本块。
-
尺寸为250x40。
-
字体大小(在"样式"标头下)为20。
-
-
利用与在上一菜单中创建按钮的相同方式,即可创建带文本块标签的游戏按钮。
-
对于按钮:将命名改为PlayGameButton, 位置 改为(200,300), 尺寸 改为(200,100)
-
对于文本块:将命名改为PlayGameText,将 可见性 设为"命中测试不可见",并将其拖到PlayGameButton的顶部。
-
-
"开始游戏"按钮将有一个特殊功能:仅在文本框中输入非空白命名时启用。可使用 虚幻运动图形 (UMG)绑定功能新建 已启用(Is Enabled) 字段(在 行为(Behavior) 部分下)的功能。
GameMode 上公开 UFUNCTION 或在项目中的某处公开静态函数。但由于仅需名称字符串不为空,因此可在 控件
-
为确保仅在文本框非空白时启用按钮,可将文本框中的文本转换为字符串,然后检查其长度是否大于零。以下为此逻辑的显示方式:
-
再添加一个按钮,以便退出并从此处进入主菜单。添加方式与添加主菜单的"开始游戏"按钮相同,但其位置位于右下角而非左上角。为了完成此操作,点击 细节面板 中的 锚 下拉列表,并在弹出菜单中找到适当的图示。
-
将命名改为MainMenuButton
-
将 位置 设为(-400,-200)
-
将 尺寸 设为200x100
将锚放在右下角,此操作不会改变其大小和位置值的工作方式,因此需将位置值设为负值,使其在屏幕中显示。保留尺寸值为正。
-
-
现在再次添加 OnClicked 事件,向新按钮添加脚本。主菜单按钮将简单重加载主菜单控件,在 ChangeMenuWidget 函数的调用中不提供新控件,开始游戏按钮将停止菜单。显示短语 选择类 而非实际类或资产的命名,可对此进行显示。
Pawn
-
现在应该具备两种屏幕,大致如下:
6.自行尝试!
利用所学内容,尝试以下操作:
-
同时打开的多个菜单。
-
在屏幕上滑入或淡入 控件 ,而非直接显示。
-
查看控件支持的不同声音、样式和颜色属性。
-
在菜单中设置 **GameMode 内如难度、角色级别等变量。
-
创建游戏内菜单,可在玩家按键时弹出并暂停游戏,而在关闭后可继续游戏。
-
将之前教程中构建或学习的功能关联到在 虚幻示意图形 (UMG)中构建的菜单。
本教程中讲解的相关细节:
-
欲了解在UMG中设计游戏进程屏幕显示和使用诸多可用控件,请阅读 UMG界面设计器用户指南 或 控件类型参考 页面。
-
欲了解公开变量和函数及在菜单中使用 定时器 和 事件 的更多相关信息,参见 变量、定时器和事件 页面。
-
欲学习更多教程,参见 C++ 编程教程 页面。