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++ 编程教程页面。