虚幻-4-游戏开发精要-全-
虚幻 4 游戏开发精要(全)
原文:
zh.annas-archive.org/md5/c3cb2c574f80ae3cab48a85f03e3bf6b译者:飞龙
前言
虚幻引擎 4 游戏开发基础的目的是教那些对使用虚幻引擎感兴趣的人如何创建视频游戏。您将学习虚幻引擎是什么以及如何下载和使用它。从那里,我们将介绍虚幻引擎 4 中可用的工具集合,包括材质、蓝图、Matinee、UMG、C++等。
本书涵盖内容
第一章, 虚幻引擎 4 简介,是我们开始学习虚幻引擎 4 游戏开发基础之旅的地方。在这一章中,读者将学习如何下载虚幻引擎以及源版本和启动版本之间的区别。在引擎安装(或编译,如果是源版本)之后,我们将熟悉虚幻引擎的用户界面。我们还将了解内容浏览器、BSP 的基本知识,以及如何更改游戏的启动画面和图标。
第二章, 导入资产,教您在引擎启动并运行后如何将自定义 FBX 资产导入到虚幻引擎中。您将了解碰撞、材质和细节级别。
第三章, 材质,介绍了材质编辑器以及用于为您的资产创建着色器的常用节点。在学习了材质的基础知识后,我们将创建一个示例材质函数,该函数可以改变法线图的强度。
第四章, 后期处理,在介绍材质之后继续讲解后期处理。在这一章中,您将学习如何覆盖默认的后期处理设置。之后,我们将学习如何添加自己的后期处理体积,并了解一个简单但非常强大的功能,称为 LUT。之后,我们将创建一个可以与后期处理一起使用的特殊材质,该材质将具有突出显示用户定义对象的能力。
第五章, 灯光,使我们在虚幻引擎 4 游戏开发基础之旅中走了一半,这一章将向您介绍照明系统。我们首先介绍基础知识,例如放置灯光和查看常见设置。然后,您将了解更多关于 Lightmass 全局照明系统的内容,包括如何为与 Lightmass 一起使用的资产正确准备 UV 通道。到本章结束时,您将学习如何使用 Lightmass 以及 Lightmass 设置来构建场景。
第六章, 蓝图,教您什么是蓝图以及引擎中可用的各种蓝图类型。蓝图是虚幻引擎中允许艺术家和设计师快速原型化他们的游戏(甚至制作一个!)的首要工具。您还将了解不同的图形类型,例如事件图、函数图、宏图等,以及如何在运行时动态生成蓝图。
第七章, Matinee,探讨了虚幻引擎 4 的电影方面及其相关工具,即 Matinee。您将了解 Matinee 是什么,如何创建它,并熟悉用户界面。在基础之后,我们将学习如何在 Matinee 中操纵对象以及创建一个非常基本的场景,我们将使用蓝图来触发它。
第八章, 虚幻运动图形,教您如何创建一个基本的显示玩家健康的用户界面(HUD)。虚幻运动图形(UMG)是虚幻引擎中的 UI 编写工具。UMG 用于创建玩家 HUD、主菜单、暂停菜单等。您还将学习如何创建 3D 小部件,这些小部件可以放置在世界中或附加到演员类。
第九章, 粒子,探讨了名为级联粒子编辑器的极其强大且稳健的工具,并创建了一个粒子系统,因为没有好的视觉效果的游戏是不完美的。然后我们将它与简单的蓝图脚本结合,以创建随机爆发的粒子。
第十章, 虚幻 C++ 简介,在我们接近 虚幻引擎 4 游戏开发基础 旅程的终点时,回顾了 C++。在这一章中,您将学习如何获取 Visual Studio 2015 社区版,并通过检查第三人称模板角色类来学习 C++ 的基础知识。然后我们将扩展这个类以添加对健康和健康恢复系统的支持。您还将学习如何将变量和函数暴露给蓝图编辑器。
第十一章, 打包项目,将我们带入了 虚幻引擎 4 游戏开发基础 的旅程终点。在这一章的最后一章,我们将回顾我们所做的一切,包括一些小贴士,最后,您将学习如何创建游戏的发布版本。
您需要这本书的内容
虚幻引擎 4.9 或更高版本
这本书面向的对象
这本书的目标读者是任何对使用虚幻引擎 4 学习游戏开发感兴趣的人。如果您对开发游戏充满热情,并想了解虚幻引擎 4 及其工具的基础知识,那么这本书将帮助您快速入门。虚幻引擎 4 将是您迈向为所有平台(包括移动设备和游戏机)创建下一代视频游戏的下一步。
术语约定
在本书中,您将找到许多文本样式,用于区分不同类型的信息。以下是一些这些样式的示例及其含义的解释。
文本中的代码单词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 昵称如下所示:“这为引擎添加或删除一个路径(它可以是虚拟包路径,如\Game\MyContent\,或绝对路径,如C:\My Contents)以监控新内容。”
代码块设置如下:
void APACKT_CPPCharacter::RegenerateHealth()
{
if (Health >= GetClass()->GetDefaultObject<ABaseCharacter>()->Health)
{
Health = GetClass()->GetDefaultObject<ABaseCharacter>()->Health;
}
else
{
Health += RegenerateAmount;
FTimerHandle TimerHandle_ReRunRegenerateHealth;
GetWorldTimerManager().SetTimer( TimerHandle_ ReRunRegenerateHealth, this, &APACKT_CPPCharacter::RegenerateHealth, RegenDelay );
}
}
新术语和重要词汇以粗体显示。屏幕上显示的单词,例如在菜单或对话框中,在文本中显示如下:“一旦您登录,您可以通过点击“获取虚幻引擎”下的大橙色下载按钮来下载启动器。”
注意
警告或重要注意事项以如下框的形式出现。
小贴士
小技巧和技巧如下所示。
读者反馈
读者的反馈总是受欢迎的。让我们知道您对这本书的看法——您喜欢或不喜欢什么。读者反馈对我们很重要,因为它帮助我们开发出您真正能从中获得最大收益的标题。
要向我们发送一般反馈,请简单地发送电子邮件至 <feedback@packtpub.com>,并在邮件主题中提及本书的标题。
如果您在某个主题上具有专业知识,并且您对撰写或为本书做出贡献感兴趣,请参阅我们的作者指南www.packtpub.com/authors。
客户支持
现在您是 Packt 图书的骄傲拥有者,我们有一些可以帮助您充分利用购买的东西。
下载示例代码
您可以从www.packtpub.com的账户下载本书的示例代码文件。如果您在其他地方购买了这本书,您可以访问www.packtpub.com/support并注册,以便将文件直接通过电子邮件发送给您。
您可以通过以下步骤下载代码文件:
-
使用您的电子邮件地址和密码登录或注册我们的网站。
-
将鼠标指针悬停在顶部的支持选项卡上。
-
点击代码下载与勘误。
-
在搜索框中输入书名。
-
选择您想要下载代码文件的书籍。
-
从下拉菜单中选择您购买此书的来源。
-
点击代码下载。
文件下载完成后,请确保使用最新版本解压或提取文件夹:
-
WinRAR / 7-Zip for Windows
-
Zipeg / iZip / UnRarX for Mac
-
7-Zip / PeaZip for Linux
下载本书的颜色图像
我们还为您提供了一个包含本书中使用的截图/图表的颜色图像的 PDF 文件。这些颜色图像将帮助您更好地理解输出的变化。您可以从 www.packtpub.com/sites/default/files/downloads/UnrealEngine4GameDevelopment%20Essentials_ColorImages.pdf 下载此文件。
勘误
尽管我们已经尽一切努力确保内容的准确性,但错误仍然可能发生。如果您在我们的某本书中发现错误——可能是文本或代码中的错误——如果您能向我们报告这一点,我们将不胜感激。通过这样做,您可以节省其他读者的挫败感,并帮助我们改进本书的后续版本。如果您发现任何勘误,请通过访问 www.packtpub.com/submit-errata,选择您的书籍,点击勘误提交表单链接,并输入您的勘误详情来报告它们。一旦您的勘误得到验证,您的提交将被接受,勘误将被上传到我们的网站或添加到该标题的勘误部分下的现有勘误列表中。
要查看之前提交的勘误,请访问 www.packtpub.com/books/content/support,并在搜索字段中输入书籍名称。所需信息将出现在勘误部分下。
盗版
互联网上对版权材料的盗版是一个持续存在的问题,涉及所有媒体。在 Packt,我们非常重视保护我们的版权和许可证。如果您在互联网上发现我们作品的任何非法副本,请立即提供位置地址或网站名称,以便我们可以寻求补救措施。
请通过 <copyright@packtpub.com> 联系我们,并提供涉嫌盗版材料的链接。
我们感谢您在保护我们作者和我们为您提供有价值内容的能力方面的帮助。
问题
如果您对本书的任何方面有问题,您可以通过 <questions@packtpub.com> 联系我们,我们将尽力解决问题。
第一章。Unreal Engine 4 简介
欢迎来到 Unreal Engine 4 游戏开发基础。在本章中,您将学习如何下载 Unreal Engine 的源代码版本和启动器版本。之后,我们将熟悉 Unreal Engine 4 用户界面和内容浏览器。
Unreal Engine 4 下载
Unreal Engine 4 完全免费(包括所有未来的更新!)下载和使用。您将获得所有 Unreal Engine 工具、免费样本内容、完整的 C++ 源代码,包括整个编辑器的代码及其所有工具;您还将获得访问官方文档的权限,包括教程和支持资源,以及访问 UE4 市场 place,它提供大量免费和商业内容。
Unreal Engine 4 可以下载两种不同的版本。一个是二进制版本(启动器),另一个是源代码版本(GitHub)。GitHub 版本和启动器版本之间的区别如下:
-
启动器(二进制)版本:这些由 Epic 编译并通过启动器提供。您还将获得启动器版本的所有源文件(
*.cpp),但您不能对 Unreal Engine 进行任何修改,因为启动器版本不会生成解决方案文件。 -
GitHub 版本:这些版本没有二进制文件,因此您必须自己编译引擎。您将获得整个源代码,并且可以在 Unreal Engine 中修改几乎任何内容。您可以添加新的引擎功能,修改现有功能或删除它们(没有人这样做),并在 GitHub 上创建拉取请求,如果 Epic 喜欢它,他们将会将其官方集成到 Unreal Engine 中。
在本指南中,我将向您展示如何获取这两个版本。
下载启动器版本
要下载 Unreal Engine 的启动器版本,显然您需要启动器。要下载启动器,请按照以下步骤操作:
-
首先前往
www.unrealengine.com/并使用您的凭证登录。 -
登录后,您可以通过点击 获取 Unreal Engine 下的大橙色 下载 按钮来下载启动器。
![下载启动器版本]()
安装后首次打开启动器,它应自动下载 Unreal Engine 4 的最新版本。如果它没有这样做,请转到 库 选项卡并点击 添加引擎。现在将出现一个新的引擎槽,在这里您可以选择您的 Unreal Engine 版本并安装它。

下载 GitHub 版本
要下载 Unreal Engine 4 的源代码,请按照以下步骤操作
-
首先创建一个 GitHub 账户(免费!)。
-
之后,您需要前往
www.unrealengine.com/dashboard/settings并更新您的 GitHub 账户名称,然后点击 保存:![下载 GitHub 版本]()
分支 Unreal Engine 仓库
在你成功将 GitHub 账户与虚幻引擎账户链接后,你需要登录到 GitHub 并导航到虚幻引擎仓库。
注意
确保你已经将你的 GitHub 账户链接到你的虚幻引擎账户。否则,你将看不到虚幻引擎仓库。
当你在仓库页面时:
-
点击页面右上角的 Fork。
-
选择你的用户名以将其分叉到你的 GitHub 仓库。
-
然后,你需要下载 GitHub for Windows(如果你使用 Windows)或 GitHub for Mac(如果你使用 Mac)并安装它。
你需要这个 Git 客户端来克隆(下载)你分叉的仓库,对虚幻引擎进行自己的修改,并将更改作为拉取请求提交给 Epic 以集成到编辑器中。
要克隆你的分叉仓库,请按照以下步骤操作:
-
启动 GitHub 并使用你的凭证登录。
-
点击 Git 客户端左上角的加号(+)。
-
然后,点击 克隆 选项卡并选择你的 用户名(你现在应该能看到虚幻引擎)。
-
现在,点击 克隆虚幻引擎 并选择你想要保存虚幻引擎仓库的文件夹。
-
点击 确定。
-
你现在应该看到 GitHub 正在将虚幻引擎克隆到你的硬盘上。
![Forking Unreal Engine repository]()
一旦克隆完成,导航到那个目录并运行 Setup.bat 文件。
-
这将下载编译引擎所需的所有必要文件,并安装所有必需的先决条件。
-
这可能需要一些时间,具体取决于你的网速,因为它需要下载超过 2 GB 的文件。
编译虚幻引擎
一旦 Setup.bat 完成,运行 GenerateProjectFiles.bat,这将生成 Visual Studio 解决方案文件。打开 UE4.sln 文件,现在,你就可以编译你自己的虚幻引擎 4 版本了。现在,在 解决方案资源管理器 中右键点击 UE4 并点击 构建。

这将根据你的系统硬件从 15 分钟到 1 小时不等。所以请坐下来,拿一杯咖啡,等待引擎编译完成。
熟悉虚幻引擎
一旦你的引擎编译完成(或如果你使用启动器下载,则下载完成)是时候启动它了:
-
启动你的自定义构建:你可以按 Visual Studio 中的 F5 键以启动调试引擎,或者导航到下载它的目录,进入
Engine\Binaries\Win64文件夹并双击UE4Editor.exe。 -
启动启动器构建:只需点击那个大 启动 按钮即可。
注意
当你第一次编译后启动引擎时,可能会遇到长时间加载的情况。这是因为虚幻引擎将优化你的平台内容以生成数据缓存。这是一个一次性过程。
在启动画面之后,你现在应该能看到虚幻项目浏览器。执行以下步骤:
-
选择新建项目选项卡,这就是你创建新项目的地方。
-
对于这本书,我们将坚持使用空白蓝图项目。因此,在蓝图选项卡中,选择空白项目。
-
你可以选择你想要的项目平台。有两个平台可供选择:桌面/控制台和移动/平板。请随意更改你项目的此设置。第二个设置确定你平台的图形设置。如果你选择桌面/控制台,最好坚持使用最高质量;如果你的项目针对移动/平板,你应该选择可伸缩的 3D 或 2D,这是针对低端 GPU 的。第三个也是最后一个设置让你可以从 Epic 添加一些入门内容,其中包含一些基本的网格、材质和纹理。你可以选择不包含入门内容,这样项目将只包含所选项目的必需元素。
-
注意,在为移动/平板平台创建项目时,不建议包含入门内容。这可能会显著增加你项目的包大小。
-
为你的项目选择一个名称以及你想要保存它的位置。
-
最后,点击创建项目以使用你的项目启动 Unreal Engine 4:
![熟悉 Unreal Engine]()
这就是 Unreal Engine 用户界面的样子:

一旦 Unreal Engine 启动,你应该会看到一个类似于前面的截图的场景。这是如果你选择包含入门内容时将默认显示的场景。如果你跳过入门内容,则启动场景将不同。
视口工具栏
视口工具栏包含你在整个关卡设计过程中将使用的各种工具。让我们快速浏览一下:

-
变换工具:这三个工具是移动工具、旋转工具和缩放工具。
-
坐标系:这允许你将你的 Actor 在世界轴(世界空间)或其自身的本地轴(本地空间)上移动、旋转或缩放。默认情况下,Unreal 编辑器以世界轴开始,但你可以通过点击图标来切换。地球图标表示世界空间,立方体图标表示本地空间。
-
吸附和移动网格:吸附允许你将一个 Actor 吸附到另一个 Actor 的表面上,移动网格允许你在场景内吸附到三维隐式网格上。
-
旋转网格:这提供了增量旋转吸附。
-
缩放网格:这会自动调整到增量值。
提示
移动、旋转和缩放的吸附首选项可以在编辑器首选项中调整。转到编辑 | 编辑器首选项 | 视口,然后滚动到网格吸附类别。
-
相机速度:这让你可以控制相机在视口中的移动速度。
提示
您可以通过按住鼠标右键(同时使用 WASD 控制键)并上下滚动鼠标滚轮来调整相机速度,从而加快或减慢相机的移动。
-
最大化视口:此选项在单个视口和 4 视口分割样式之间切换。
小贴士
您可以通过更改 布局 选项来调整 视口 的布局,如下面的截图所示:
![视口工具栏]()
在本章的后面部分,您将学习如何使用 二叉空间划分(BSP)以及更改一些项目设置,如 启动 屏幕和游戏 图标 等。
模式
模式 选项卡包含编辑器的所有五种模式。具体如下:
-
放置 模式(快捷键是 Shift + 1):放置 模式允许您快速放置最近放置的对象,以及引擎原语,如灯光、几何形状、触发器、体积等。
-
绘制 模式(快捷键是 Shift + 2):绘制 模式(也称为 网格绘制)允许您在 视口 中的 静态网格 上交互式地绘制顶点颜色。
-
景观 模式(快捷键是 Shift + 3):景观 模式允许您在 Unreal 编辑器中完全创建新的景观,或从外部程序(如 World Machine、TerreSculptor 等)导入高度图,并对它进行修改。
-
植被 模式(快捷键是 Shift + 4):植被 模式允许您在 景观、其他静态网格等上绘制或擦除多个静态网格。一个示例工作流程是在大区域上绘制草地、树木等。
-
几何编辑 模式(快捷键是 Shift + 5):几何 模式允许您编辑 BSP 刷子。

内容浏览器
内容浏览器 是您项目的核心所在。在这里,您可以创建、导入、查看、编辑、组织和修改游戏中的所有资产。它还允许您像在 Windows 资源管理器中一样重命名、删除、复制和移动资产到其他文件夹。此外,内容浏览器还允许您根据关键词或资产类型搜索特定资产,并且您可以通过添加 '-'(连字符)作为前缀来排除资产。
您还可以创建 集合 来整理您常用的资产,以便快速访问。
小贴士
集合只是资产的引用,并不会移动到集合中。这意味着单个资产可以存在于多个集合中,并且您可以创建无限数量的集合。
有三种类型的集合:
-
共享集合:这些对您和其他用户可见。此选项仅在您已启用 源 控制(例如:Perforce、Subversion 等)时才激活。
-
私有集合:这些只对被邀请查看集合的人可见。此选项仅在您已启用 源控制(例如:Perforce、Subversion 等)时才激活。
-
本地集合:这些仅为你所有。这意味着它们只存在于你的本地机器上。
如果你想要将资产从一个项目转移到另一个项目,你可以右键单击该资产并选择迁移…,这将复制该资产及其所有依赖项到你的新项目。
内容浏览器可以通过按Ctrl+Shift+F或从菜单栏上的Windows菜单访问。你还可以同时打开四个内容浏览器实例。
这在你想要将资产移动到不同的文件夹或预览不同文件夹中的各种资产时非常有用。

内容浏览器视图选项
视图选项让你可以执行以下操作:
-
更改缩略图大小
-
更改视图样式
-
修改 3D 缩略图,等等
视图选项可以从内容浏览器的右下角访问。

世界大纲
世界大纲以树形视图显示了级别内的所有角色。可以从世界大纲中选择和修改角色。在世界大纲中右键单击角色将显示与视口中相同的上下文菜单,这样你就可以在不进入视口的情况下修改它。你可以将一个角色拖动到另一个角色上并将它们连接在一起。
世界大纲允许你搜索特定的角色。你可以在搜索词前添加-(连字符)来排除特定的角色,你可以在搜索词前添加+来强制匹配确切术语。

细节面板
细节面板显示了视口中选择的全部信息、实用工具和功能。它显示了所选角色的所有可编辑属性,并根据所选角色提供额外的功能。例如,如果你选择了一个蓝图,细节面板将显示与该蓝图相关的所有内容,包括暴露的变量、Blutility 事件等。如果你选择了一个静态网格角色,细节面板将显示应用了哪种材质、碰撞设置、物理设置、渲染设置等。细节面板可以锁定到所选角色,这样它就不会根据角色选择而改变。就像内容浏览器一样,你可以同时打开四个细节面板实例。
导航视口
你可以使用鼠标和键盘轻松地导航视口。关于导航视口的高级说明可以在这里找到:docs.unrealengine.com/latest/INT/Engine/UI/LevelEditor/Viewports/ViewportControls/index.html
小贴士
在视口的左下角有一个小问号按钮。如果你点击它,你将看到一些常用的视口快捷键。

BSP
现在我们对引擎用户界面有了些基本的了解,让我们使用 BSP 来创建一个简单的级别。BSP 是一个几何工具(也称为几何笔刷或简称笔刷),用于快速原型化级别(也称为级别布局)。一些开发者更喜欢称之为构造实体几何(CSG),这是一个更准确的术语,因为 Unreal 编辑器中的几何形状是通过添加和减去笔刷来创建的。BSP 自 Unreal 的第一个版本以来就存在了。它曾用于很久以前的级别设计,但后来,这个角色被静态网格所取代,因为 BSP 在性能上更昂贵。
所以基本上,BSP 应该只用于原型化一个级别。一旦你对一个级别应该看起来怎样有了基本的概念,你应该开始用静态网格替换它。
小贴士
CSG 和 BSP 可以互换用来指代 Unreal 中的几何形状。两者是相同的。
创建 BSP
Unreal Engine 4 附带七个笔刷,并且它们都可以在细节面板中进行自定义。它们如下:
-
盒子: 你可以调整X、Y和Z轴,并将其设置为空心,这是一个快速制作房间的快捷方式,并调整墙厚,它定义了内部墙壁的厚度。
-
圆锥: 你可以在细节面板中自定义边数、高度以及外半径和内半径。你还可以将其设置为空心,并调整墙厚来定义内部墙壁的厚度。
-
圆柱: 你可以在细节面板中自定义边数、高度以及外半径和内半径。你还可以将其设置为空心,并调整墙厚来定义内部墙壁的厚度。
-
曲线楼梯: 这将创建一个在角度周围弯曲的楼梯形状,但不能缠绕自身。
-
直线楼梯: 这将创建一个不弯曲的直楼梯。
-
螺旋楼梯: 这将创建一个可以反复缠绕自身的螺旋楼梯。
-
球体: 这将创建一个球形。半径可以在细节面板中自定义。
就像任何其他演员一样,您可以使用变换工具来移动、旋转和缩放,以适合您的需求。
有两种类型的笔刷。它们如下:
-
加法: 这些笔刷是实心的。这将添加几何形状到级别中。例如,您将使用加法类型来创建墙壁、地板、天花板等。
-
减法: 这些笔刷是空心的。这将减去之前创建的加法笔刷中的实体空间。例如,您将使用减法类型在墙上创建窗户或门。
你还可以将 BSP 几何形状转换为静态网格,并将它们保存在内容浏览器中,但请记住,它们将没有 UV 或额外的材质元素。这也值得提一下,这不是一个好的或推荐的流程。你应该只使用 BSP 来布局你的级别,然后,你应该导入从 DCC 应用程序创建的资产。
小贴士
您可以进入几何编辑模式(Shift+F5)来编辑顶点并创建自定义形状。
默认起始关卡、启动画面和游戏图标
您可以更改游戏和编辑器的默认起始关卡。例如,对于游戏,您可能希望将主菜单地图作为默认,而对于编辑器,您可能希望另一个关卡作为默认启动级别。
在虚幻编辑器中设置它们很容易:
-
在菜单栏中点击编辑。
-
点击项目设置。
-
转到地图与模式。
-
在这里,您可以更改游戏和编辑器的默认地图。
![默认起始关卡、启动画面和游戏图标]()
您可以通过项目设置调整启动画面:
-
转到窗口部分。
-
从这里更改启动画面和游戏的图标。
小贴士
启动画面的默认尺寸为600 x 200,需要.bmp图像。游戏图标需要256 x 256的.ICO文件。

摘要
现在您已经了解了虚幻引擎的基础知识,是时候从 3ds Max、Maya 或 Blender 等 DCC 应用程序中导入一些资源了。在下一章中,我们将创建一个简单的网格在 3ds Max 中,并将其导入到虚幻引擎中,并介绍各种选项,例如设置材质、碰撞和 LOD。
第二章:导入资源
在上一章中,你学习了 Unreal Engine 的基础知识。在本章中,你将学习如何从 Autodesk 3ds Max 导入资源。
在 DCC 应用程序中创建资源
在上一章中,你学习了如何使用 BSP 来阻挡关卡。然而,我们需要用静态网格来替换它们,以获得更好的性能和更多对材质、碰撞等方面的控制。我们将在 数字内容创作 (DCC) 应用程序(如 Autodesk 3ds Max、Autodesk Maya、Blender 等)中创建模型,并通过内容浏览器导入 Unreal Engine。Unreal Engine 支持导入 FBX 和 OBJ 格式,但建议使用 FBX 格式。
以下截图是本章中将使用的示例资源:

注意
注意,在撰写本书时,Unreal Engine 的导入管道使用 FBX 2014。尝试使用不同版本导入可能会导致不兼容。
在建模时需要记住的一些事项如下:
-
单位:Unreal 单位(UU)在为游戏建模资产时至关重要。错误的单位会导致资产看起来比预期的大或小。1 Unreal 单位等于 1 厘米。Unreal Engine 4 中的示例角色高 196 厘米。因此,当你为 Unreal Engine 4 建模资产时,最好使用一个高 196 厘米的盒子作为参考。
注意
要了解如何更改 Autodesk 3ds Max 的单位,你可以参考
knowledge.autodesk.com/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/3DSMax/files/GUID-69E92759-6CD9-4663-B993-635D081853D2-htm.html。要了解如何更改 Blender 的单位,你可以参考
www.katsbits.com/tutorials/blender/metric-imperial-units.php。-
轴点:这代表对象的局部中心和局部坐标系。当你将网格导入 Unreal Engine 时,该网格的轴点(正如它在你的 DCC 应用程序中一样)决定了任何变换(如移动、旋转和缩放)将执行的位置。通常,最好将你的网格保持在原点(0, 0, 0)并将轴点设置在网格的一个角落,以便在 Unreal Engine 中正确对齐。
-
三角化:记住,Unreal Engine 导入器会自动将四边形转换为三角形,因此不会跳过三角形。
-
UV:当你为资产进行 UV 时,你可以超出 0-1 空间,特别是当你处理大型对象时。UV 通道 1(在 Unreal 中是通道 0)用于纹理,UV 通道 2(在 Unreal 中是通道 1)用于光照贴图。
-
创建碰撞网格
您可以创建碰撞网格并将其与您的资产一起导出。Unreal Engine 4 为静态网格提供碰撞生成器,但有时我们必须创建自己的自定义碰撞形状,特别是如果网格有开口(如门或带有窗洞的墙)。在本节中,我们将看到这两种选项。
小贴士
碰撞形状应始终保持简单,因为计算简单形状要快得多。
自定义碰撞形状
碰撞网格由 Unreal 导入器根据其名称识别。您可以定义三种类型的碰撞形状。它们如下:
-
UBX_MeshName:UBX 代表 Unreal Box,正如其名,它应该呈箱形状。您不能以任何方式移动顶点,否则它将不起作用。
-
USP_MeshName:USP 代表 Unreal Sphere,正如其名,它应该呈球形状。此球体的分段数量并不重要(尽管大约 6-10 似乎不错),但您不能移动任何顶点。
-
UCX_MeshName:UCX 代表 Unreal Convex,正如其名,它应该是一个凸形状,不应该有空或凹。这是最常用的碰撞形状,因为基本形状(如箱体和球体)可以直接在 Unreal 中生成。
在下面的屏幕截图中,您可以看到红色的线框对象,这是我为了碰撞形状而创建的:

Unreal Engine 4 碰撞生成器
静态网格的碰撞形状可以在静态网格编辑器内生成。要打开此编辑器,请双击内容浏览器中的静态网格资产,然后点击碰撞菜单,这将列出所有碰撞选项。

简单形状
此菜单中的前三个选项是简单形状,如下所示:
-
球体碰撞:这创建了一个简单的球体碰撞形状
-
胶囊碰撞:这创建了一个简单的胶囊碰撞形状
-
箱体碰撞:这创建了一个简单的箱体碰撞形状
![简单形状]()
K-DOP 形状
K 离散定向多面体(K-DOP)形状基本上是边界体积。数字(10、18 和 26)代表 K 轴对齐的平面。
自动凸形碰撞
此选项用于创建更精确的碰撞形状以供您的模型使用。一旦您点击此选项,静态网格编辑器右下角将出现一个新的浮动窗口;使用最大壳体(创建以最佳匹配对象形状的壳体数量)和最大壳体顶点(确定碰撞壳体的复杂性)您可以创建更复杂的碰撞形状,用于您的静态网格。
如您在以下屏幕截图中所见,自动凸形的结果相当准确:

小贴士
碰撞形状支持变换(移动、旋转和缩放),并且您可以复制它们以拥有多个碰撞。在静态网格编辑器中单击碰撞形状,您可以使用W、E和R在移动、旋转和缩放之间切换。您可以使用Alt + 左键单击拖动(或Ctrl + W)来复制现有的碰撞。
材质
Unreal Engine 可以在从 3D 应用程序导出时将材质和纹理应用到网格上。从 Autodesk 3ds Max,只支持基本材质。它们是标准和多/子对象。在这些基本材质中,只支持特定功能。这意味着 FBX 不会导出所有设置,但它支持该材质类型中使用的某些贴图或纹理。
在以下示例中,您可以看到分配了多个材质的模型。
注意
注意,在多/子对象材质中为每个子材质拥有唯一的名称非常重要。每个子材质都有一个唯一的名称,如下面的截图所示:

级别细节(LOD)
细节级别(LOD)是一种限制网格随着它们远离相机时影响的方法。每个 LOD 与上一个相比将具有较少的三角形和顶点,并且可以具有更简单的材质。这意味着基础 LOD(LOD 0)将是当玩家靠近时出现的高质量网格。当玩家远离该对象时,它将变为LOD 1,其三角形和顶点比LOD 0少,当玩家进一步远离时,它将切换到LOD 2,其三角形和顶点比LOD 1少得多。
以下图应能给您一个关于 LOD 做什么的思路。左边的网格是基础 LOD(LOD 0),中间是LOD 1,右边是LOD 2。
注意
更多关于 LOD 的信息可以在docs.unrealengine.com/latest/INT/Engine/Content/Types/StaticMeshes/HowTo/LODs/index.html找到。

导出和导入
我们现在将介绍如何将网格导出和导入到 Unreal 中。
导出
导出网格是一个相当直接的过程。您可以在单个 FBX 文件中导出多个网格,或者单独导出每个网格。Unreal 导入器可以在导入时将多个网格作为单独的资产导入,或者通过在导入时启用合并网格选项将它们合并为一个资产。
在以下截图中,您可以看到我已经选择了碰撞网格和模型以进行导出:

注意
平滑组在导出时应该开启,否则 Unreal Engine 在导入时会显示警告。
导入
将网格导入到 Unreal 中很简单。您有三种导入方式。它们在这里解释。
上下文菜单
您可以在内容浏览器内部右键单击并选择导入到 <您的文件夹名称>。

拖放
如其名所示,你可以轻松地将 FBX 或 OBJ 模型从Windows 资源管理器拖放到内容浏览器以进行导入。
内容浏览器导入
内容浏览器有一个导入按钮,你可以使用它来导入网格。

自动导入
如果你将 FBX 文件放置在你的项目内容文件夹中(包括任何子文件夹),Unreal 将自动检测并触发导入过程(如果你已经打开了编辑器。否则,下次运行时)。
配置自动导入
你可以选择是否启用或禁用此选项。要配置,请转到编辑 | 编辑器首选项 | 加载与保存 | 自动重新导入。

-
监控内容目录:这可以启用或禁用资产的自动导入。
-
要监控的目录:这为引擎添加或删除一个路径(它可以是一个虚拟包路径,如
\Game\MyContent\,或一个绝对路径,如C:\My Contents)以监控新内容。 -
自动创建资产:如果启用,任何新的 FBX 文件将不会自动导入。
-
自动删除资产:如果启用,并且你从资源管理器中删除了 FBX 文件,Unreal Engine 将提示你是否要删除资产文件。
结果
当你导入你的资产时,你将看到导入选项对话框。你可以在这里阅读有关导入设置的详细信息:

一旦你点击导入(如果你正在导入多个 FBX 文件,则为导入全部),你将在内容浏览器中看到资产。在下面的截图中,你可以看到 Unreal 如何自动从 Autodesk 3ds Max 导入材质:

如果你双击静态网格(Tower_Example),你将看到静态网格编辑器。在下面的截图中,你可以看到 Unreal 成功导入了我的自定义碰撞形状。

摘要
在下一章中,你将了解更多关于材质和纹理的内容。
第三章:材料内容
材料是一种资产,它使用包括图像(纹理)和数学表达式在内的各种图节点来定义网格的外观。由于虚幻引擎 4 利用基于物理的渲染(PBR),创建金属、混凝土、砖块等逼真材料可以相当容易。虚幻引擎中的材料定义了网格表面的所有内容,例如其颜色、光泽、凹凸度和细分,甚至可以通过操纵顶点来动画化对象!在这个时候,您可能会想“好吧,材料仅用于网格”,但实际上,它们并不局限于网格。您还使用材料进行贴图、后期处理和光照功能。
创建材料是一个相当直接的过程。您只需在内容浏览器中右键单击,选择材料,并给它一个名称。完成!

材料用户界面
现在我们已经了解了材料是什么以及它做什么,让我们看看材料图的用户界面。

工具栏
工具栏面板包含各种按钮,有助于预览图形节点、删除孤立节点、材料统计信息等。让我们看看这些按钮的功能:
-
保存: 应用您对材料所做的更改并保存资产
![工具栏]()
-
在 CB 中查找: 在内容浏览器中导航并选择此材料
![工具栏]()
-
应用: 将更改应用到材料。请注意,这不会保存材料
![工具栏]()
-
搜索: 搜索材料表达式或注释
![工具栏]()
-
主页: 导航到并选择主画布节点
![工具栏]()
-
清理: 删除未连接的节点
![工具栏]()
-
连接器: 显示或隐藏未连接的引脚
![工具栏]()
-
实时预览: 切换预览材料的实时更新
![工具栏]()
-
实时节点: 切换图形节点的实时更新
![工具栏]()
-
实时更新: 为图中的每个节点重新编译着色器
![工具栏]()
-
统计信息: 切换材料统计信息和编译错误
-
移动统计信息: 与统计信息相同,但针对移动设备
![工具栏]()
实时节点对于新用户可能有些令人困惑,所以我将进一步解释它们。
实时预览
有时候在将特定节点连接到主节点之前或进行调试目的时,我们需要预览该节点的结果。
要预览节点,您需要在节点上右键单击并选择开始预览节点。

除非您启用实时预览,否则您将看不到预览材料中的任何更改。
小贴士
您可以按空格键强制预览。
实时节点
这将显示由于对节点所做的表达式更改而导致的节点实时更新。请参见以下示例:

在前面的屏幕截图中,正弦节点正在从时间接收恒定更新,乘以一。如果你启用实时节点,你会看到正弦节点在黑白之间脉冲。如果你将乘法值从1更改为任何其他值(例如,5),除非你同时启用实时更新,否则你将看不到变化。
实时更新
当启用时,每次你进行更改(如添加新节点、删除节点、更改属性等)时,所有表达式都会重新编译。如果你有一个复杂的图,建议禁用此选项,因为它必须每次你进行更改时编译所有节点。
预览面板
预览面板显示了当前正在编辑的材质的结果。你可以使用以下选项在预览材质中导航:
-
旋转网格:使用左鼠标按钮拖动
-
平移:使用中间鼠标按钮拖动
-
缩放:使用右鼠标按钮拖动
-
更新光照:按住L键并使用左鼠标按钮拖动
在预览视口的右上角,你可以更改一些设置。这会将预览网格更改为所选的原始形状:

这将预览网格更改为自定义网格。你需要在内容浏览器中静态网格:

这切换了预览视图中网格的渲染:

这切换了预览视口中的实时渲染:

细节面板
细节面板显示当你选择图中的节点时可以编辑的所有属性。如果没有选择节点,它将显示材质本身的属性。
有关这些设置的更多信息,请访问docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/MaterialProperties/index.html的材质属性文档。
图面板
这是创建所有决定材质外观和行为节点的主体区域。默认情况下,材质图包含一个具有一系列输入的主节点,并且此主节点不能被删除。一些输入被灰色显示,可以通过在细节面板中更改混合模式来启用。

调色板面板
调色板面板列出了可以拖放到图中的所有图节点和材质函数。
小贴士
使用类别选项,你可以过滤调色板内容在表达式或材质函数之间。
常见材质表达式
在我们创建材质时,我们经常使用一些常见的材质节点。要创建节点,您需要在图形画布上右键单击并搜索它,或者您可以使用 调色板 窗口进行拖放。一些节点也分配了快捷键。
让我们来看看这些常用节点。
常量
常量表达式输出一个单一的浮点值,可以连接到几乎任何输入。您可以将常量表达式转换为参数,并实时更改材质实例。您还可以通过蓝图或 C++ 访问参数,并在游戏中查看更改。
-
快捷键:按住 1 并单击图形区域
-
参数快捷键:按住 S 并单击图形区域
-
示例用法:使纹理变亮或变暗
小贴士
常量参数被称为标量参数

您可以看到一个常量表达式(0.2)被用来使纹理变暗。
Constant2Vector
Constant2Vector 表达式输出两个浮点值,这是一个二维向量值(例如,红色通道和绿色通道)。您可以将 Constant2Vector 转换为参数,并实时更改材质实例,或者在蓝图或 C++ 中访问它,以在游戏运行时对材质进行动态更改。
-
快捷键:按住 2 并单击图形区域
-
参数快捷键:按住 V 并单击图形区域
-
示例用法:分别调整纹理的 UV 坐标

您可以在前面的屏幕截图中看到 Constant2Vector 被用来平铺纹理。
Constant3Vector
Constant3Vector 表达式输出三个浮点值,这是一个三通道向量值(例如,红色通道、绿色通道和蓝色通道)。您可以将 Constant3Vector 转换为参数,并实时更改材质实例,或者在蓝图或 C++ 中访问它,以在游戏运行时对材质进行动态更改。
-
快捷键:按住 3 并单击图形区域
-
参数快捷键:按住 V 并单击图形区域
-
示例用法:更改给定纹理的颜色

您可以在前面的屏幕截图中看到 Constant3Vector 被用来着色灰度纹理。
纹理坐标 (TexCoord)
纹理坐标表达式输出纹理 UV 坐标作为二维向量(例如,U 和 V),这有助于平铺,并允许您使用不同的 UV 坐标。
- 快捷键:按住 U 并单击图形区域

前面的屏幕截图显示了使用纹理坐标来平铺纹理。您可以通过查看左下角的 详细信息 面板来查看使用的值。
乘法
此表达式将给定输入相乘并输出结果:
-
乘法是按通道进行的。例如,如果你要乘以两个向量(0.2, 0.3, 0.4)和(0.5, 0.6, 0.7),实际过程如下:
0.2 x 0.5 = 0.1 0.3 x 0.6 = 0.18 0.4 x 0.7 = 0.28因此,输出结果如下:
(0.1, 0.18, 0.28) -
乘法 节点期望输入类型相同,除非其中一个为常量。简而言之,你不能将 Constant2Vector 和 Constant3Vector 相乘,但你可以将 Constant2Vector 或 Constant3Vector 与一个常量表达式相乘。
- 快捷键:按住 M 并点击图形区域
![乘法]()
前面的截图显示了一个乘法节点被用来增强发射效果。
加法
此表达式将给定的输入相加并输出结果:
加法是按通道进行的。例如,如果你要加两个向量(1, 0, 0)和(0, 1, 0),实际过程如下:
1 + 0 = 1
0 + 1 = 1
0 + 0 = 0
因此,输出结果如下:
(1, 1, 0)
加法 节点期望输入类型相同,除非其中一个为常量。简而言之,你不能将 Constant2Vector 和 Constant3Vector 相加,但你可以将 Constant2Vector 或 Constant3Vector 与一个常量表达式相加。让我们看看为什么是这样的。请看以下截图:

在这里,我们试图将 Constant3Vector 和 Constant2Vector 相加,但它不会工作。这是因为,当材质编辑器尝试编译 加法 节点时,由于 Constant3Vector 的最后一个元素没有可以相加的内容,它将失败。它将像以下计算一样:
1 + 2 = 3
1 + 2 = 3
1 + ? = fail
但你可以将 Constant3Vector 加到一个常量表达式中,如下图所示:

结果将如下所示:
1 + 2 = 3
1 + 2 = 3
1 + 2 = 3
这将编译无误。
- 快捷键:按住 A 并点击图形区域
![加法]()
除法
此除法表达式将给定的输入除并以输出结果:
除法是按通道进行的。例如,如果你要除以两个向量(0.2, 0.3, 0.4)和(0.5, 0.6, 0.7),实际过程如下:
0.2 / 0.5 = 0.4
0.3 / 0.6 = 0.5
0.4 / 0.7 = 0.571
因此,输出结果如下:
(0.4, 0.5, 0.571)
除法 节点期望输入类型相同,除非其中一个为常量。简而言之,你不能将 Constant2Vector 除以 Constant3Vector,但你可以将 Constant2Vector 或 Constant3Vector 除以一个常量表达式。
- 快捷键:按住 D 并在图形区域中点击
![除法]()
减法
此表达式从给定的输入中减去并输出结果:
减法是按通道进行的。例如,如果你要从两个向量(0.2, 0.3, 0.4)和(0.5, 0.6, 0.7)中减去,实际过程如下:
0.2 - 0.5 = -0.3
0.3 - 0.6 = -0.3
0.4 - 0.7 = -0.3
因此,输出结果如下:
(-0.3, -0.3, -0.3)
减法 节点期望输入类型相同,除非其中一个为常量。简而言之,你不能从 Constant3Vector 中减去 Constant2Vector,但你可以从 Constant2Vector 或 Constant3Vector 中减去一个常量表达式。
- 快捷键:没有快捷键
![减法]()
纹理采样(Texture2D)
纹理采样输出给定的纹理。它还分别输出纹理的所有四个通道(即红色、绿色、蓝色和 alpha),以便您可以使用它们进行各种操作。这对于处理多个灰度纹理(如遮罩纹理、粗糙度纹理等)特别有用。您不必导入多个纹理,只需在 Photoshop 中创建一个纹理,并将其他纹理分配给不同的通道,在材质编辑器中,您可以获取每个通道并执行所有这些复杂操作。哦,我提到过 Texture2D 还可以使用电影纹理吗?
您可以将纹理采样转换为TextureSampleParameter2D,并通过材质实例实时更改纹理。您还可以通过蓝图或 C++在游戏中动态更改纹理。
-
快捷键:按住 T 并在图形区域单击
-
参数快捷键:无快捷键

组件遮罩
组件遮罩表达式可以从输入中提取不同的通道,输入应该是向量通道,例如Constant2Vector、Constant3Vector、Constant4Vector、TextureSample等。例如,Constant4Vector 只有一个输出,即 RGBA。因此,如果您想从 RGBA 中获取绿色通道,您将使用组件遮罩。您可以在组件遮罩上右键单击,将其转换为参数,并在材质实例中进行实时更改。
-
快捷键:无快捷键
-
参数快捷键:无快捷键
![组件遮罩]()
在此屏幕截图中,我们提取 alpha 通道并将其连接到不透明度,并将 RGB 通道连接到基础颜色。
线性插值(lerp)
这根据 alpha 值混合两种纹理或值。当 alpha 值为0(黑色)时,使用A输入。如果 alpha 值为1(白色),则使用B输入。大多数情况下,这是根据遮罩纹理混合两种纹理。
-
快捷键:按住 L 并在图形区域单击
-
示例用法:根据 alpha 值混合两种纹理,该值可以是常数或遮罩纹理
![线性插值(lerp)]()
在这里,lerp 节点输出 100%的输入A,因为 alpha 值为0。如果我们设置 alpha 值为1,那么我们将看到 100%的B。如果 alpha 值为0.5,那么我们将看到A和B的混合。
功率
功率节点将基础输入乘以自身 Exp 次。例如,如果您在基础中有4,在指数中有6,那么实际过程是这样的:
4 x 4 x 4 x 4 x 4 x 4 = 4096
因此,功率的结果是4096。
如果您将纹理应用到基础输入,并且有一个常数值(例如,4),那么纹理将被乘以四次。
-
快捷键:按住 E 并在图形区域单击
-
示例用法:调整高度图或环境遮挡图的对比度
![功率]()
前面的图像显示了使用 Power 节点来增强纹理采样对比度的用法。
PixelDepth
PixelDepth输出当前正在渲染的像素到摄像机的距离。这可以用来根据玩家距离改变材料的视觉效果。
-
快捷键:无快捷键
-
示例用法:根据玩家距离改变物体的颜色
![PixelDepth]()
如果你将之前的材料应用到网格上,那么网格的颜色将根据玩家摄像机距离而改变。

前面的截图显示了网格在玩家摄像机附近的视觉效果。

前面的截图显示了网格在远离玩家摄像机时的外观。
去饱和度
正如标题所说,去饱和度表达式会去饱和其输入。简单来说,它可以根据一定百分比将彩色图像转换为灰度图像。
- 快捷键:无快捷键

时间
此表达式输出游戏的时间流逝(以秒为单位)。如果你想让你的材料随时间变化,可以使用此功能。
-
快捷键:无快捷键
-
示例用法:创建一个脉冲材料
![Time]()
在之前的材料中,我们将时间乘以一个常量表达式。乘法节点的结果连接到正弦节点,该节点输出一个连续的振荡波形,其值在-1到1的范围内。然后我们使用常量偏移缩放节点来防止值低于0。常量偏移缩放节点基本上是一个向输入添加偏移值并将其乘以缩放值的节点。默认情况下,偏移设置为0.5,缩放为1。所以如果正弦值为-1,那么结果是(-1 + 1) * 0.5,等于0。
Fresnel
Fresnel创建边缘照明,这意味着它将突出网格的边缘。
- 快捷键:无快捷键
![Fresnel]()
之前网络的输出结果如下:

材料类型
现在你已经了解了一些基本表达式,让我们来看看不同的材料类型。首先,显然是主要的材料编辑器,但随后你还有材料实例、材料函数和分层材料。
材料实例
材料实例用于在不重新编译的情况下更改材料的外观。当您在材料编辑器中更改任何值并应用它时,它将重新编译整个着色器并创建一组着色器。当您从该材料创建材料实例时,它将使用同一组着色器,因此您可以在不重新编译任何内容的情况下实时更改值。但是,当您在父材料中使用静态切换参数或组件遮罩参数时,情况就不同了,因为每个参数都有独特的组合。例如,假设您有一个没有静态切换参数的Material_1,以及一个具有名为bEnableSwitch的静态切换参数的Material_2。Material_1将只创建一组着色器,而Material_2将创建两组着色器,分别对应bEnableSwitch = False和bEnableSwitch = True。
一个示例工作流程是创建一个包含所有必要参数的主材料,并让设计师制作不同的版本。
材料实例有两种类型。它们是:
-
材料实例常量
-
材料实例动态
只有材料实例常量具有用户界面。材料实例动态没有用户界面,并且不能在内容浏览器中创建。
材料实例常量
正如标题所说,材料实例常量(MIC)只能在编辑器中编辑。这意味着您不能在运行时更改值。MIC 公开了您在父材料中创建的所有参数。您可以创建自己的组并很好地组织所有参数。

材料实例用户界面
-
工具栏(1): 以下为工具栏选项:
-
保存: 保存资产
-
在 CB 中查找: 在内容浏览器中导航到该资产并选择它
-
参数: 公开父材料的所有参数
-
移动统计: 切换移动材料的统计信息
-
-
详细信息(2): 显示父材料及其材料实例的所有参数。在这里,您还可以分配一个物理材料并覆盖父材料的基属性,例如混合模式、双面等。
-
实例父级(3): 这里您将看到一系列父级,直到主主材料。当前正在编辑的实例以粗体显示。
-
视口(4): 视口在网格上显示材料,以便您可以在实时中看到您的更改。您可以在右上角更改预览形状。这与材料编辑器中的相同。
材料实例常量示例
为了使材料实例工作,我们需要一个具有参数的主材料。让我们创建一个简单的材料,它将根据与玩家的距离改变其颜色,也就是说,当玩家靠近网格时,它将呈现红色,当玩家远离时,它的颜色将改变。请注意,UE4 中有 21 个参数表达式。
目前我们将坚持使用两个常见的参数,如下所示:
-
标量参数
-
矢量参数
![材质实例常量示例]()
如您在前面的截图中所见,我们创建了两个矢量参数(Color1、Color2)和两个标量参数(TransitionDistance、Speed)。我们将使用这些参数进行实时修改。要创建此材质的实例,您需要在内容浏览器中右键单击此材质,并选择创建材质实例。这将在此材质旁边创建一个新的实例材质。
如果您打开该实例,您将看到所有这些参数都在那里,并且您可以在不等待材质重新编译的情况下实时编辑它们:

要更改材质实例中的值,您需要首先覆盖它们。您需要点击参数附近的复选框来覆盖值。如下面的截图所示:

材质函数
材质函数是包含一组节点且可用于任何数量材质的图表。如果您经常发现自己创建复杂的网络,那么创建一个材质函数会更好,这样您就可以将这些复杂的网络包含在一个单独的节点中。需要注意的是,材质函数不能包含任何参数节点(例如,标量参数、矢量参数、纹理参数等)。要将数据传递到材质函数中,您需要使用特殊的函数输入节点。同样,如果您想从材质函数中获取数据,您需要使用函数输出节点。默认情况下,材质函数为您创建一个输出,但您可以根据需要创建更多输出。
材质函数的 UI 几乎与材质编辑器相同。如果您检查详细信息面板,您将看到一些选项,可以帮助您充分利用材质函数。让我们看看这些选项:
-
描述:当您在材质图中将鼠标悬停在此函数节点上时,它将显示为工具提示。
-
暴露到库中:启用此选项,当您在材质图中右键单击时,将显示您的材质函数。
-
库分类:此列表显示此函数所属的分类。默认情况下,它属于杂项分类,但您可以更改它并添加尽可能多的分类。
小贴士
材质函数不能应用于表面,因此如果您想使用材质函数,必须在材质中使用它。
材质函数示例
要创建材质函数,首先在内容浏览器中右键单击,转到材质与纹理并选择材质函数。在这个例子中,我们将创建一个名为法线图调整器的材质函数,它可以增强法线图的强度。让我们看看创建此类函数需要什么:
-
纹理 [输入]:显然我们需要传递一个需要修改的纹理。
-
强度 [输入]:我们还需要传递正常应该有多强的信息。0的值表示不更改正常贴图,而1的值表示增强正常效果。
-
结果 [输出]:最后我们将输出结果,我们可以将其连接到我们的材质中的正常通道。
小贴士
最终输出节点(结果)可以重命名为任何你想要的自定义名称。选择节点,在细节面板中,更改输出名称。
打开你的材质函数,在图表上右键单击并搜索输入。

选择函数输入节点。你将在细节面板中看到你刚刚选择的输入节点的某些属性。

让我们来看看这些设置:
-
输入名称:输入的自定义名称。你可以取任何你想要的名称。在这里,我将其命名为法线纹理。
-
描述:当你在材质图表中悬停在此输入上时,将用作工具提示。
-
输入类型:定义了此节点的输入类型。
-
预览值:如果此输入在材质图表中没有连接,则使用的值。仅在使用预览值作为默认值被选中时使用。
-
使用预览值作为默认值:如果选中,它将使用预览值并将此输入标记为可选。因此,当你使用此函数时,你可以不连接此输入。但是,如果你禁用此选项,那么在材质图表中,你必须连接所需的节点到此处。
-
排序优先级:安排此输入与其他输入节点的关系。
让我们创建一个简单的网络来增强正常效果。看看下面的截图:

在这里,我们正在分别提取红色、绿色和蓝色通道。这样做的原因很简单,我们只需要将强度(标量输入值)与蓝色通道相乘以增强正常效果。强度需要在0和1之间夹紧,然后使用1-x(OneMinus)节点进行反转,因为我们使用这个材质函数在材质中时,需要0作为默认的正常强度,1则真正增强效果。如果没有 OneMinus 节点,则相反,即0将增强正常贴图效果,1将产生常规效果。
函数完成后,点击工具栏上的保存按钮。
小贴士
自动保存会编译材质。
现在要将此放入材质中,在材质图表内右键单击并搜索NormalMapAdjuster。然后你只需要将一个Normal贴图和一个标量参数连接到NormalMapAdjuster,并将其连接到Normal通道。
小贴士
如果它没有出现在上下文菜单中,请确保你在材质功能中启用了暴露到库。

在你的材质实例中,你可以实时调整NormalIntensity。
分层材质
分层材质基本上是材质中的材质,并且作为材质函数的扩展存在。基本工作流程如下:你创建一个Make Material Attribute(它具有所有材质属性,如Base Color、Metallic、Specular、Roughness等),并将你的节点连接到它。然后,将Make Material Attributes的输出连接到Output Result节点的输入。
当你的资产具有不同的材质层时,分层材质最有益。例如,考虑一个具有不同元素的角色,如金属装甲、皮革手套、皮肤等。以传统方式定义这些材质并将它们混合在一起将显著增加材质的复杂性。如果你在这种情况下使用分层材质,你可以将每个材质定义为单个节点,并非常容易地混合它们。
使用 make material attributes 创建分层材质
对于本例,我们将创建两个简单的分层材质并将它们在我们的最终材质中混合在一起。首先,创建一个材质函数并打开它。在材质函数中,按照以下步骤操作:
-
右键点击图编辑器,搜索Make Material Attributes并从菜单中选择该节点。
-
创建一个Constant3Vector节点并将其连接到Make Material Attributes的BaseColor。
-
创建一个常量值并将其连接到Make Material Attributes的Metallic。
-
创建另一个常量值并将其连接到Make Material Attributes的Roughness。
-
最后,将Make Material Attributes连接到材质函数的输出。
最终的材质函数应如下所示。注意我使用的常量节点值。

由于我们希望这是Metallic,我们将Metallic设置为1。
我们将创建这个相同的材质函数的副本,并将其制作为一个具有不同颜色的非金属材质。请参见以下图片:

这是一个非金属材质,我们将在材质编辑器中使用默认的Material Layer Blend函数将这两个材质混合在一起。
确保公开这两个材质函数,这样我们就可以在材质编辑器中使用它们。
在内容浏览器中打开一个现有的材质或创建一个新的材质,并打开它:
-
右键点击图并搜索你的材质函数(选择两个)。
-
再次右键点击图并搜索并选择MatLayerBlend_Simple。
-
将你的材质函数连接到MatLayerBlend_Simple。将一个函数连接到Base Material,另一个连接到Top Material。
-
现在,为了混合这两种材质,我们需要一个Alpha (标量)值。值为1(白色)将输出基础材质,值为0将输出顶层材质。值为0.5将输出基础和顶层材质的混合。
由于我们使用的是分层材质,我们不能像其他节点那样直接将其连接到材质编辑器。为了使此功能正常工作,有两种连接方式。
方法 1:
我们可以使材质使用材质属性而不是常规节点。要使用此功能,请点击图上的任何位置,然后在详细信息面板中选择使用材质属性:

当您启用此功能时,主材质节点将只显示一个名为材质属性的节点,这样您就可以将MatLayerBlend_Simple的输出连接到该节点。
以下是用此方法创建的最终材质的截图:

方法 2:
在此方法中,我们不是使用材质属性作为主节点,而是使用BreakMaterialAttributes并将它们作为常规节点连接:
-
右键单击图区域,搜索并选择BreakMaterialAttributes。
-
将MatLayerBlend_Simple的输出连接到BreakMaterialAttributes。
-
最后,将BreakMaterialAttributes的所有输出节点连接到材质编辑器的主节点。
以下是用此方法创建的最终材质的截图:

摘要
在下一章中,我们将使用后处理技术来增强场景的外观。我们还将创建一个简单的材质并在后处理材质中使用它。
第四章 后处理
Unreal Engine 4 中的后处理允许你创建各种艺术效果,并改变整个游戏的整体外观和感觉。后处理效果通过后处理体积激活,可以单独使用以影响特定区域或整个场景。你可以有多个重叠的后处理体积,并根据它们的优先级渲染它们的效果。后处理体积可以用来添加或修改简单的效果,如光晕、镜头光晕、眼睛适应、景深等,它们也可以用来使用材质获取高级效果。后处理体积的另一个伟大功能是查找表(LUT),它用于存储来自图像编辑软件(如 Adobe Photoshop 或 GIMP)的颜色转换。它们非常容易设置,并且可以产生非常好的效果。我们将在本章后面讨论 LUT。
当你开始一个没有起始内容的项目时,场景中将不会出现后处理体积,因此引擎将使用默认设置。你可以在项目设置中按项目更改这些设置:
-
在菜单栏中点击编辑。
-
点击项目设置。
-
转到渲染部分。
-
展开默认后处理设置:
![后处理]()
在这里,你会看到当场景中没有后处理体积时,Unreal Engine 的默认设置。你可以修改这些设置或添加一个后处理体积来独立覆盖它们。
添加后处理
要使用后处理,你需要在场景中有一个后处理体积:
-
转到模式标签(如果你已关闭它,请按Shift + 1)。
-
选择体积标签。
-
将后处理体积拖放到场景中:
![添加后处理]()
你现在场景中有一个后处理体积。然而,它只显示当玩家在该体积内时的效果。要使其影响整个场景,请执行以下步骤:
-
选择后处理体积
-
在详细信息面板中,向下滚动并展开后处理体积部分
-
启用未绑定
启用未绑定将忽略此体积的边界并影响整个场景。现在,让我们快速查看这些后处理设置:

-
优先级:如果有多个体积重叠,则优先级较高的体积将覆盖优先级较低的体积。
-
混合半径:这是用于混合的体积的半径。通常,
100的值效果最佳。如果你启用了未绑定,则此设置将被忽略。 -
混合权重:这定义了属性的影响。
0表示无效果,1表示全效果。 -
启用:此选项启用或禁用此体积。
-
未绑定:如果启用,则后处理效果将忽略此体积的边界并影响整个场景。
LUT
LUT 是颜色中性的纹理,展开到 256 x 16 大小的纹理。它们用于创建独特的艺术效果,并使用图像编辑软件(如 Adobe Photoshop)进行修改。如果你不熟悉 Photoshop,可以使用免费和开源软件,如 GIMP。以下是一个默认 LUT 纹理的图像:

LUT 的流程如下:
-
首先,你拍摄你的世界的一张快照,并将其带入 Photoshop。
-
在上面的截图上,插入 LUT 纹理。
-
然后在两者之上应用色彩调整(例如:调整图层)。
-
现在选择 LUT 纹理,并将其与你的色彩调整一起保存为 PNG 或 TGA。
-
最后,将你的 LUT 导入 Unreal Engine。
注意
注意,在你将 LUT 导入内容浏览器后,打开它并将纹理组设置为色彩查找表。这是一个重要的步骤,不应跳过。
要应用 LUT,选择后处理体积,然后在场景颜色部分,你可以启用色彩分级并设置你的 LUT 纹理:

使用色彩分级强度选项,你可以改变效果强度。
后处理材料
后处理材料帮助你通过材质编辑器创建自定义后处理。你需要创建一个具有你所需效果的材质,并将其分配给后处理体积中的可混合项。点击加号以添加更多插槽:

在我解释后处理材料之前,让我们快速看一下材质编辑器中最重要的一些后处理节点之一:
-
场景纹理:此节点有多个选择,输出不同的纹理:
![后处理材料]()
-
UVs(可选):此输入平铺纹理。对于场景纹理节点的 UV 操作,使用屏幕位置节点而不是常规的纹理坐标节点是很好的。
-
颜色:这输出最终的纹理作为 RGBA。如果你想将其与颜色相乘,首先需要使用组件遮罩提取 R、G 和 B,然后乘以你的颜色。
-
大小:这输出纹理的大小(宽度和高度)。
-
InvSize:这是大小输出的倒数。(1/宽度 和 1/高度)。
注意
需要记住的是,只有在你真正需要的时候才应该使用后处理材料。对于色彩校正和各种其他效果,你应该坚持使用后处理体积的设置,因为它们更高效且经过优化。
创建后处理材料
使用后处理材料,你可以创建自己的自定义后处理效果。一些例子包括:
-
在你的游戏中突出显示特定对象
-
渲染遮挡对象
-
边缘检测等
在这个快速示例中,我们将看到如何突出显示我们世界中的对象。要单独渲染特定对象,我们需要将它们放入自定义深度缓冲区。好事是,这就像点击一个复选框一样简单。
选择你的静态网格,在Rendering部分下展开选项并启用Render Custom Depth:

现在网格已渲染在CustomDepth缓冲区中,我们可以在材质编辑器中使用此信息来遮罩并单独渲染它。要这样做:
-
创建一个新的材质并打开它。
-
现在首先要做的是将Material Domain设置为Post Process。这将禁用所有输入,除了Emissive Color。
-
现在,右键单击图表并搜索SceneTexture并选择它。将Scene Texture Id设置为CustomDepth。
-
CustomDepth输出一个原始值,所以让我们将其除以我们想要的距离。
-
添加一个新的Divide节点并将CustomDepth连接到输入A。选择除法节点,并为Const B提供一个高值(例如:
100000000)。记住,1 Unreal Unit 等于1厘米,所以如果你提供一个像100或1000这样的小值,你需要非常接近对象才能看到效果。这就是为什么我们使用一个非常大的值。 -
添加一个Clamp节点并将Divide连接到Clamp节点的第一个输入。
-
创建一个Lerp节点并将Clamp的输出连接到Lerp的Alpha输入。Lerp节点将根据 alpha 值混合输入 A 和 B。如果 alpha 值为
1,则使用输入A。如果是0,则使用输入B。 -
创建另一个SceneTexture节点并将其Scene Texture Id设置为PostProcessInput0。PostProcessInput0输出最终 HDR 颜色,所以请确保使用它。还有一个名为SceneColor的输出,它做同样的事情,但输出当前场景的较低质量。
-
再次右键单击图表并搜索Desaturation节点。将PostProcessInput0的Color输出连接到Desaturation输入。我们将使用它来降低除了带有CustomDepth的网格之外整个场景的饱和度。
-
将Desaturation输出连接到Lerp B和PostProcessInput0到Lerp A,最后将Lerp连接到Emissive Color。
下面是整个图表的最终截图:

在这个示例场景中,我已经将此材质应用于后处理混合体,你可以看到效果:

所有有颜色的内容都启用了 Render Custom Depth,所以后处理材质正在遮罩它们并将去饱和度应用于整个场景。
摘要
在下一章中,我们将添加灯光并讨论光移动性、光照质量和动态灯光。
第五章。灯光
灯光是您游戏中一个重要的因素,很容易被忽视,并且不当的使用会严重影响性能。但是,通过适当的设置,结合后期处理,您可以创建非常美丽和逼真的场景。
在本章中,我们将探讨不同的灯光移动性,并深入了解由 Epic 游戏创建的静态全局照明求解器 Lightmass 全局照明。我们还将学习如何准备与它一起使用的资产。
灯光基础
在本节中,我们将了解如何放置灯光以及如何调整一些重要值。
放置灯光
在 Unreal Engine 4 中,灯光可以通过两种不同的方式放置。通过模式标签或通过在关卡中右键单击:
-
模式标签:在模式标签中,转到位置标签(Shift + 1)并转到灯光部分。从那里您可以拖放各种灯光。
![放置灯光]()
-
右键单击:在视图中右键单击,在放置演员中您可以选择您的灯光。
![放置灯光]()
一旦灯光被添加到关卡中,您可以使用变换工具(W键移动,E键旋转)来更改所选灯光的位置和旋转。
提示
由于方向光来自无限远的来源,更新它们的位置没有效果。
各种灯光
Unreal Engine 4 具有四种不同类型的灯光演员。它们是:
-
方向光:模拟来自无限远处的光源。由于此光源产生的所有阴影都将平行,因此这是模拟阳光的理想选择。
-
聚光灯:从单个点以锥形发射光。有两个锥体(内锥体和外锥体)。在内锥体内部,灯光达到全亮度,在内锥体和外锥体之间发生衰减,这会柔和照明。这意味着在内锥体之后,灯光的照明会随着它向外锥体移动而逐渐减弱。
-
点光源:从单个点向所有方向发射光,就像现实世界中的灯泡一样。
-
天空光:实际上并不发射光,而是捕获场景的远处部分(例如,放置在天空距离阈值之外的演员)并将它们作为光应用。这意味着您可以从大气、远处的山脉等地方获得灯光。请注意,天空光只有在您重建灯光或按重新捕获场景(在细节面板中选择天空光)时才会更新。
常见灯光设置
现在我们已经了解了如何将灯光放置到场景中,让我们来看看一些常见的灯光设置。在场景中选择您的灯光,在细节面板中您将看到这些设置:
-
强度:确定灯光的强度(能量)。这是以流明为单位,例如,1700 lm 相当于 100 瓦的灯泡。
-
灯光颜色:确定灯光的颜色。
-
衰减半径:设置光线的限制。它还会计算光线的衰减。此设置仅在点光源和聚光灯中可用。
![常见光线设置]()
从左到右的衰减半径:100,200,500。
-
源半径:定义表面上的镜面高光大小。此效果可以通过调整最小粗糙度设置来减弱。这也会影响使用光线质量的建筑物照明。较大的源半径会产生更柔和的阴影。由于这是通过光线质量处理的,因此它仅适用于设置为静态移动性的光线。
![常见光线设置]()
源半径 0. 注意阴影的锐利边缘。
![常见光线设置]()
源半径 5. 注意阴影的柔和边缘。
-
源长度:与源半径相同。
光线移动性
在放置你的关卡中的光线时,光线移动性是一个需要记住的重要设置,因为它会改变光线的工作方式并影响性能。你可以选择三个设置。它们如下所示:
-
静态:这是一种完全静态的光,不会影响性能。此类光线不会在动态对象(例如,角色、可移动对象等)上产生阴影或镜面反射。示例用法:在玩家永远不会到达的地方使用此光线,例如遥远的城市景观、天花板等。你可以有数百万个具有静态移动性的光线。
-
静止:这是一种静态和动态光线的混合,在游戏运行时可以改变其颜色和亮度,但不能移动或旋转。静止光线可以与动态对象交互,并用于玩家可以到达的地方。
-
可移动:这是一个完全动态的光,所有属性都可以在运行时更改。可移动光线对性能的影响较大,因此应谨慎使用。
只允许四个或更少的静止光线相互重叠。如果你有超过四个静止光线相互重叠,光线图标将变为红色 X,这表示光线正在以严重的性能成本使用动态阴影!

在以下屏幕截图中,你可以轻松看到重叠的光线。

在视图模式下,你可以切换到静止光线重叠以查看哪个光线导致了问题。
光线质量全局照明
Lightmass 是由 Epic Games 创建的高质量静态全局照明求解器。全局照明(GI)意味着模拟间接照明的过程(例如,光线反射和表面颜色渗透)。在 Unreal Engine 中,默认情况下,光线通过 Lightmass 进行反射,并基于你的材质的基础颜色,这控制了从物体表面反射多少光线。尽管更饱和的颜色会反射更多光线,而较不饱和的颜色会反射较少,但这都取决于场景。在一个简单的房间场景中,这可能是明显的,而如果是户外白天场景,这可能不那么明显。
让我们快速看一下以下场景:

这是一个在无光照模式下的简单场景。

现在我添加了一束方向光,这是没有 GI 时的样子。这意味着只有直接照明,没有间接照明(意味着没有光线反射)。

上一张截图是使用静态全局照明(GI),你可以看到整个场景因为 GI 而变得生动起来。注意柱子是如何投射阴影的。这些被称为间接阴影,因为它们来自间接光。
间接光的强度和颜色取决于光线反射的材质的光和基础颜色。为了说明这个效果,让我们看看以下两张截图:

在这里,我将纯红色材质(红色值为 1.0)应用到球体上,你可以看到反射照明拾取了红色球体的基础颜色,改变了环境。这被称为颜色渗透,在高度饱和的颜色中最明显。

在这张截图中,我将红色的值改为 0.1 并重新构建了照明。由于红色现在更暗,反射的光更少。这是因为较暗的颜色会吸收光线而不是反射它。
现在我们已经知道了什么是 Lightmass,让我们来看看如何准备我们的资产以使用 Lightmass,并了解更多关于 Lightmass 设置的信息。
为预计算照明准备你的资产
为了使你的资产具有干净的光照和阴影细节,有必要拥有独特的未展开 UV 来表示其自己的空间以接收暗和亮的信息。在创建光照贴图 UV 时,一个经验法则是 UV 面不应与 UV 空间内的任何其他面重叠。这是因为如果它们重叠,那么在光照构建之后,对应该空间的光照贴图将应用于两个面,这将导致不准确的光照和阴影错误。重叠的面对于正常纹理 UV 来说很好,因为每个面的纹理分辨率都会更高,但对于光照贴图 UV 来说,这个规则不适用。在 3D 程序中,我们将光照贴图 UV 展开到新的通道,并在虚幻引擎 4 中使用该通道。

在这里,你可以看到我正在使用网格的第二个通道进行光照贴图。
注意
虚幻引擎从 0 开始计数,而大多数 3D 程序从 1 开始计数。这意味着 3D 程序中的 UV 通道 1 在虚幻引擎中是 UV 通道 0,UV 通道 2 在虚幻引擎中意味着 UV 通道 1。在这里,在前一张截图中,你可以看到光照贴图坐标索引是1,这意味着它正在使用网格的第二个 UV 通道。
尽管你可以在虚幻引擎 4 中生成光照贴图 UV,但强烈建议在 3D 程序(例如,Autodesk Maya、Autodesk 3dsmax、Modo 等)中创建这些 UV,以便获得干净的光照贴图。在创建光照贴图 UV 之前,你必须在 3D 应用程序的 UV 编辑器中设置网格设置。例如,如果你有一个需要 128 分辨率的资产,那么你的网格设置应该是1/126,即0.00793650。128 将是光照贴图纹理的分辨率。更高的值,如 256、512、1024 等,将产生高质量的光照贴图,但也会增加内存使用。一旦我们决定我们的资产需要的光照贴图分辨率,我们就从该分辨率中减去 2(你也可以使用 4)。这样做的原因是,为了使 Lightmass 能够正确计算而不会出现任何过滤溢出错误,建议 UV 之间至少有 2 个像素的间隙。所以如果你的资产将要使用 128 的光照贴图分辨率,它将是128 – 2 = 126。我们之所以将其除以 1,是因为默认情况下,Lightmass 使用 1 像素的边界进行过滤。
一旦你将网格导入虚幻引擎 4,你就可以为你的静态网格设置光照贴图分辨率。这个值控制着当另一个对象在这个对象上投射阴影时,阴影看起来有多好。
光照贴图是由虚幻引擎生成的纹理,并叠加到你的场景之上。由于这是一个纹理,它应该以 2 的幂(例如,16、32、64、128、256、512、1024 等)的形式存在。

前一张截图中的地板光照贴图分辨率为32。请注意地板上的阴影不准确。

前一个截图中的地板光照贴图分辨率为256。注意地板上的阴影效果更好。
注意
尽管提高光照贴图分辨率可以提供准确的光影效果,但并不是在每个网格中都提高分辨率的好主意,因为这会严重增加构建时间,甚至可能使整个编辑器崩溃。对于较小的对象,保持较低的分辨率总是好主意。
在虚幻引擎 4 中,您可以在导入网格时通过启用生成光照贴图 UV来生成光照贴图 UV。

如果您错过了这个选项,您仍然可以在导入后生成光照贴图 UV。为此,请执行以下步骤:
-
在内容浏览器中双击静态网格。
-
然后,在LOD选项卡下,启用生成光照贴图 UV。
-
选择源光照贴图索引。大多数情况下这将设置为0,因为那是正常纹理 UV,虚幻引擎从纹理 UV 生成光照贴图 UV。
-
设置目标光照贴图索引。这是虚幻引擎保存您新创建的光照贴图 UV 的位置。将其设置为 1。
-
点击应用更改以生成光照贴图 UV。
![为预计算光照准备您的资源]()
注意
如果您已经在目标光照贴图索引中有一个光照贴图 UV,则在生成新的光照贴图时它将被替换。
您可以通过在工具栏中点击UV按钮并选择您的UV 通道来预览 UV。

使用 Lightmass 构建场景
使用 Lightmass 构建场景是一个相当直接的过程。为了获得高质量的静态全局照明(也称为预计算光照),您需要在场景中有一个光量重要性体积。这是因为许多地图中,我们有足够大的区域,而可玩区域实际上较小。因此,我们不是计算整个场景的光照,这可能会大大增加光照构建时间,而是通过使用光量重要性体积来限制区域。
一旦我们在场景中有一个光量重要性体积并开始光照构建,Lightmass 将只计算体积内的光照。所有体积外的对象将只获得低质量的一次光反弹。
要在光量重要性体积中包围可玩区域,您只需从模式选项卡拖放即可。就像其他对象一样,您可以使用变换工具(W键移动,E键旋转,R键缩放)来调整场景中的光量重要性体积。完成这些操作后,您只需从构建按钮构建光照即可。

或者,您可以简单地按构建按钮,这将构建光照。Lightmass 有四个不同的质量级别可供选择。它们是预览、中等、高和生产。

-
预览:在开发过程中可以使用,这会导致更快地构建光线。
-
生产:当您的项目接近完成或准备发布时,您应该使用生产设置,因为它会使场景更加逼真并纠正各种光溢出错误。
小贴士
照明质量只是预设。有许多设置应该调整以获得游戏中期望的效果。
调整光子设置
Lightmass 在 世界设置 中提供了很多选项,您可以调整以获得最佳的视觉质量。您可以通过单击 设置 并选择 世界设置 来访问它们。

在 世界设置 中,展开 光子设置,你会看到各种可以调整的设置,以充分利用 光子。

控制这些设置可以帮助您在使用 Lightmass 时获得最佳的视觉质量。让我们来看看这些设置:
-
静态照明级别:此设置在构建光线时计算细节。较小的值将具有更多细节但会大大增加构建时间!较大的值可用于大型级别以降低构建时间。
-
间接照明反弹次数:这决定了光线应该从表面反弹多少次。0 表示只有直接照明,这意味着将没有全局照明,1 表示一次间接照明反弹,依此类推。反弹 1 对视觉质量贡献最大,后续反弹几乎免费,但不会增加很多光线,因为每次反弹后反弹的光线会变弱。
![调整光子设置]()
间接照明反弹次数设置为 1
-
间接照明质量:较高的设置会导致更少的噪声、斑驳等问题,但也会增加构建时间。使用此设置与 间接照明平滑度 结合可以帮助获得详细的间接阴影和环境遮挡。
-
间接照明平滑度:较高的值会导致 Lightmass 平滑化间接照明,但会失去详细的间接阴影。
![调整光子设置]()
间接照明质量和平滑度设置为 1.0
![调整光子设置]()
间接照明质量:4.0 和间接照明平滑度:0.5。注意柱子投下的阴影差异
-
环境颜色:将其想象为围绕级别的巨大球体,向所有方向发射颜色。也就是说,这充当了 HDR 环境的作用。
-
环境强度:缩放 环境颜色 的强度。
-
漫反射增强:这是在场景中增强间接照明强度的有效方法。由于间接照明会从表面反弹,这个值将增强颜色的影响。
-
使用环境遮挡:启用静态环境遮挡。由于环境遮挡需要密集的光照样本,因此在预览构建中看起来可能不好。最好在生产预设中构建时调整环境遮挡设置。
-
直接光照遮挡分数:应用于直接光照的环境遮挡量。
-
间接光照遮挡分数:应用于间接光照的环境遮挡量。
-
遮挡指数:更高的值会增加环境遮挡的对比度。
-
完全遮挡样本分数:此值确定一个对象应在其他对象上生成多少环境遮挡。
-
最大遮挡距离:一个对象对另一个对象造成遮挡的最大距离。
-
可视化材质漫反射:用导出到 Lightmass 的材质漫反射项覆盖正常直接光照和间接光照。
![调整 Lightmass 设置]()
启用材质漫反射可视化
-
可视化环境遮挡:用环境遮挡覆盖正常直接光照和间接光照。这在调整环境遮挡设置时很有用。
![调整 Lightmass 设置]()
启用环境遮挡可视化
-
体积光照样本放置比例:缩放放置体积光照样本的距离。
注意
所有这些 Lightmass 设置都需要重新构建光照。因此,如果您更改了这些设置中的任何一个,请确保重新构建光照以使更改生效。
体积光照样本由 Lightmass 在光照构建后的级别中放置,用于动态对象,如角色,因为 Lightmass 只为静态对象生成光照贴图。这也被称为间接光照缓存。
在以下屏幕截图中,您可以看到可移动对象(红色球体)是如何使用间接光照缓存进行照明的:

使用间接光照缓存

没有间接光照缓存
注意
体积光照样本仅放置在Lightmass 重要性体积内和静态表面上。
间接光照缓存也有助于预览未构建光照的对象。在光照构建后,如果您移动一个静态对象,它将自动使用间接光照缓存,直到下一次光照构建。
要可视化体积光照样本,请点击显示 | 可视化 | 体积光照样本。

在级别中预览的体积光照样本。
注意
您可以在后期处理体积中调整全局光照强度和颜色。在后期处理体积中,展开后期处理设置 | 全局光照,在那里您可以看到颜色和强度的设置。

要切换特定的照明组件以进行调试,您可以在显示 | 照明组件部分使用各种照明组件标志。例如,如果您想预览您的场景而不使用任何直接照明,您可以关闭直接照明,仅预览间接照明的场景。请注意,这些功能仅适用于编辑器,并且不会影响您的游戏。这些功能仅用于调试目的。

摘要
在本章中,我们学习了关于灯光的知识,以及如何通过使用 Lightmass 全局照明来提高场景的真实感,以及如何准备我们的资产以与 Lightmass 一起使用。我们还学习了各种灯光和常见设置。在下一章中,我们将深入了解 Unreal Engine 4 最独特和最佳的功能:蓝图。
第六章:蓝图
在本章中,我们将学习蓝图是什么以及如何使用它们来原型化您的游戏。我们将学习以下内容:
-
熟悉蓝图编辑器
-
各种蓝图图类型(例如,函数图、事件图等)
-
蓝图节点
-
最后,我们将创建一个简单的蓝图,可以在游戏运行时放置在世界上或动态生成。
Unreal Engine 4 中的蓝图视觉脚本是一个极其强大且灵活的基于节点的界面,用于创建游戏元素,并为艺术家和设计师提供编程游戏和快速在编辑器中迭代游戏玩法的能力,而无需编写任何代码!使用蓝图,您可以创建和调整游戏玩法、角色、输入、环境和游戏中几乎任何事物。
蓝图通过使用包含相互连接的节点的图来工作,这些节点定义了蓝图的功能。例如,它可以是对游戏事件的调用、生成新的演员,或者任何其他事情。
不同的蓝图类型
让我们快速查看在 Unreal Engine 4 中可用的各种蓝图类型:
-
级别蓝图:级别蓝图是一种特殊的蓝图,充当整个级别的全局事件图,用户无法删除或创建。每个级别都将有自己的级别蓝图,用户可以使用它来创建与整个级别相关的事件。用户可以使用此图来调用级别中特定演员的事件或播放 Matinee 序列。熟悉 Unreal Engine 3(或 UDK)的用户应该熟悉这个概念,因为这类似于那些引擎中 Kismet 的工作方式。
-
类蓝图:通常简称为蓝图,是在内容浏览器内创建的资产。一旦创建资产,就通过视觉定义其行为而不是编写任何代码。此蓝图作为资产保存在内容浏览器中,因此您可以将其拖放到您的世界中作为实例,或在另一个蓝图图中动态生成。
-
动画蓝图:这些是专门用于通过混合动画、直接控制骨骼和输出每帧的最终姿势来控制骨骼网格动画的图。动画蓝图始终有两个图,即事件图和AnimGraph。
-
事件图:这使用一系列与动画相关的事件来启动一系列节点,这些节点更新在Animgraph中驱动动画使用的值。
-
AnimGraph:用于评估您的骨骼网格的最终姿势。在此图中,您可以使用骨骼控制执行动画混合或控制骨骼变换。
-
宏库:这些是可以包含各种宏或图,您可以在任何其他蓝图类中多次使用的容器。宏库不能包含变量或从其他蓝图继承,也不能放置在级别中。它们只是您常用的一些图的集合,可以节省时间。如果您在蓝图中引用宏,则对该宏的更改不会应用到您的蓝图,直到您重新编译蓝图。编译蓝图意味着将所有属性和图转换为 Unreal 可以使用的类。
-
蓝图接口:这些是包含一个或多个未实现函数的图。添加此接口的其他类必须以独特的方式包含这些函数。这与编程中的接口概念相同,您可以使用公共接口访问各种对象并向彼此共享或发送数据。接口图有一些限制,您不能创建变量、编辑图或添加任何组件。
熟悉蓝图用户界面
蓝图用户界面(UI)默认包含多个选项卡。在下面的屏幕截图中,您可以看到蓝图 UI 的统一布局:

让我们来看看这些选项卡:
-
组件
-
我的蓝图
-
工具栏
-
图形编辑器
-
详细信息面板
组件选项卡
大多数蓝图类都可以有不同的组件类型。这些可以是灯光组件、网格组件、UI 组件等等。在本节中,我们将了解它们是什么以及我们如何在蓝图类中使用它们。
组件是什么?
组件是构成整个 Actor 的各个部分。组件不能独立存在,但添加到 Actor 后,Actor 将能够访问组件提供的所有功能。例如,考虑一辆车。车轮、车身、灯光等可以视为组件,而汽车本身作为 Actor。然后在图中,您可以访问组件并为您的汽车 Actor 执行逻辑。组件始终是实例化的,每个 Actor 实例都将有其自己的唯一组件实例。如果不是这样,那么,如果我们将多个汽车 Actor 放置在世界中,如果一个开始移动,所有其他的也将移动。
添加组件
要将组件添加到您的 Actor 中,请点击组件选项卡上的添加组件按钮。点击按钮后,它将显示您可以添加的各种组件列表。

添加组件后,您将被提示为其命名。您也可以通过从内容浏览器拖放到组件窗口直接添加组件。
要重命名组件,您可以在组件选项卡中选择它并按F2。
注意
拖放方法仅适用于静态网格、骨骼网格、声音提示和粒子系统。
选择组件后,你可以通过按Delete键来删除它。你也可以在组件上右键点击并选择删除来移除它。
变换组件
一旦组件被添加并选择,你可以使用变换工具(W、E和R)通过在详情面板或视口标签中输入值来改变组件的位置、旋转和缩放。当使用移动、旋转或缩放时,如果你在视口工具栏中启用了网格吸附,你可以按Shift来启用吸附。
注意
如果组件有任何子组件附加到它上面,那么移动、旋转或缩放该组件将传播变换到所有子组件。
为组件添加事件
根据组件添加事件非常简单,可以通过不同的方法完成。以这种方式创建的事件是特定于该组件的,无需测试涉及哪个组件:
-
从详情面板添加事件:当你选择组件时,你将在详情面板中看到该组件所有可用的事件作为按钮。当你点击任何一个时,编辑器将在事件图中为该组件创建特定的事件节点。
![为组件添加事件]()
-
通过右键点击添加事件:当你在组件上右键点击时,你将在上下文菜单中看到添加事件。从那里你可以选择任何你想要的事件,编辑器将在事件图中为该组件创建特定的事件节点。
![为组件添加事件]()
-
在图中添加事件:一旦你在我的蓝图标签页中选择了你的组件,你可以在图上右键点击并获取该组件的所有事件。
![为组件添加事件]()
我的蓝图标签页
我的蓝图标签页显示了一个列表,其中包括了蓝图内包含的图形、函数、宏、变量等等。此标签页依赖于蓝图类型。例如,类蓝图将包含事件图、构建脚本图、变量、函数、宏等等。接口将仅显示其中的函数列表。宏库将仅显示其中创建的宏。
创建按钮
你可以通过点击快捷按钮(+)在我的蓝图标签页内创建新的变量、函数、宏、事件图和事件分发器。

你也可以通过点击+添加新下拉按钮来添加它们。
在我的蓝图中进行搜索
我的蓝图标签页还提供了一个搜索区域,用于搜索你的变量、函数、宏、事件图和事件分发器。你可以根据名称、注释或其他数据进行搜索。
在我的蓝图中进行分类
总是组织你的变量、函数、宏、事件调度器等等到各种类别中是一个好习惯。在我的蓝图标签页中,你可以拥有尽可能多的类别和子类别。查看以下截图:

在这里,你可以看到我如何将所有内容组织成各种类别和子类别。要为你的变量、函数、宏和事件调度器设置类别,只需选择它们,然后在详细信息面板中输入你的新类别名称或从现有类别中选择。如果你需要子类别,则需要使用垂直线键(|)来分隔子类别名称。例如,如果你想将健康作为属性的子类别,你可以设置如下:属性 | 健康。
工具栏
工具栏提供了在编辑蓝图时所需的常用命令的访问权限。工具栏按钮将根据当前激活的模式(编辑模式、在编辑器中播放模式等)以及你当前正在编辑的蓝图类型而有所不同。
图形编辑器
图形编辑器是蓝图的主要区域。这是你添加新节点并将它们连接起来以创建定义脚本行为的网络的区域。关于如何创建新节点以及各种节点的更多信息将在本书的后续部分进行解释。
详细信息面板
详细信息面板提供了访问所选组件或变量属性的方法。它包含一个搜索字段,你可以用它来搜索特定的属性。
蓝图图类型
正如我们之前提到的,蓝图是保存在内容浏览器中的资产,用于创建新的演员类型或脚本游戏逻辑、事件等,这为设计师和程序员提供了快速迭代游戏玩法而不需要写一行代码的能力。为了让蓝图具有脚本行为,我们需要在图形编辑器中使用各种节点来定义其行为。让我们快速看一下各种图:
-
构造脚本图:构造图在蓝图初始化时执行,并且每当蓝图中的任何变量发生变化时都会执行。这意味着每次你在级别中放置蓝图实例并更改其变换或任何变量时,构造图都会执行。此图在每次构建时执行一次,并且在任何属性或蓝图更新时再次执行。这可以用于构建程序元素或设置游戏开始前的值。
-
事件图:这是包含所有游戏逻辑的地方,包括交互性和动态响应。使用各种事件节点作为函数、流程控制和变量的入口点,你可以为蓝图脚本化行为。事件图仅在开始游戏时执行。
-
函数图: 默认情况下,此图包含一个名为函数的单个入口点。此节点不能被删除,但你可以自由移动它。此图中的节点仅在你在构造图或事件图中调用此函数或从引用此函数所属蓝图的另一个蓝图调用此函数时执行。
-
宏图: 这就像是一个包含你的节点的折叠图。与函数图不同,宏可以有多个输入或输出。
-
接口图: 接口图被禁用,你不能移动、创建图、变量或组件。
注意
只有类蓝图才有构造脚本,它在游戏开始时停止执行,并被视为在游戏开始前完成。
函数图
函数图是在蓝图内部创建的节点图,可以从另一个图(如事件图或构造脚本)或从另一个蓝图执行。默认情况下,函数图包含一个单一的执行引脚,当函数被调用时激活,导致连接的节点执行。
创建函数
函数图是通过我的蓝图选项卡创建的,你可以创建任意数量的函数。
在我的蓝图选项卡中,你可以将鼠标悬停在函数标题上,然后点击+函数来添加一个新函数。

点击那个按钮(黄色高亮的按钮)将创建一个新的函数,并提示你输入一个新名称。
图形设置
当你创建一个新函数并选择它时,你将获得该函数的一些属性,你可以在详细信息面板中更改它们。让我们快速看一下它们。

-
描述: 当你在另一个图中的此函数上悬停鼠标时,会显示为工具提示。
-
类别: 保持此函数在其指定的类别中(仅用于组织目的)。
-
访问指定符: 有时当你创建函数时,你不想在另一个蓝图中访问它们。访问指定符让你指定哪些其他对象可以访问此函数。
-
公共: 这意味着任何对象都可以从任何地方访问此功能。这是默认设置。
-
受保护: 这意味着当前蓝图及其从当前蓝图派生的任何蓝图都可以访问此功能。
-
私有: 此设置意味着只有当前蓝图可以访问此功能。
-
纯函数: 当启用时,此功能被标记为纯函数,当禁用时,则为不纯函数。
-
纯函数不会以任何方式修改类的状态或成员,被视为常量函数,它只输出数据值,没有执行引脚。这些与数据引脚相连,并在需要它们上的数据时自动执行。
-
不纯函数可以自由修改类中的任何值,并包含一个执行引脚。
-
下面的截图显示了纯函数和不纯函数之间的区别:

编辑函数
要定义函数的功能,您需要编辑它。您可以拥有任意数量的输入或输出,然后在这些输入和输出之间创建节点网络来定义功能。要添加输入或输出,您首先需要在我的蓝图选项卡中选择函数,或者在打开函数图时选择主要粉红色节点。然后,在详细信息面板中,您将看到一个标有新建的按钮,该按钮创建新的输入或输出。

在这个屏幕截图中,您可以看到我如何向函数示例添加新的输入和输出。
注意
ReturnNode是可选的,并且只有在您至少有一个输出数据引脚时才会出现。如果您移除所有输出引脚,则ReturnNode将自动删除,您仍然可以使用您的函数。
例如,在下面的屏幕截图中,我创建了一个蓝图函数,为我的角色名称添加了一个前缀,这样我就可以使用这个单一函数随时更改前缀。

现在,回到事件图,我在开始播放事件上调用这个函数,这样我就可以在游戏开始时设置角色名称。

宏图
宏图实际上是节点的折叠图,其中包含由隧道节点指定的入口点和出口点,但不能包含变量。宏图可以有任何数量的执行或数据引脚。
宏可以在类蓝图或关卡蓝图内创建,就像函数一样,或者您可以在蓝图宏库中组织您的宏,该宏库可以在内容浏览器中创建。
蓝图宏库可以包含您所有的宏在一个地方,这样您就可以在任何其他蓝图中使用它们。这些可以节省大量时间,因为它们可以包含大多数常用节点并可以传输数据。但是,对宏图的更改只有在包含该宏的蓝图重新编译时才会反映出来。
要创建一个宏库,您需要在内容浏览器中右键点击,并从蓝图子类别中选择蓝图宏库。

一旦选择该选项,您必须为您的宏选择一个父类。大多数情况下,我们选择演员作为父类。选择后,您将被提示为您的宏库输入一个名称并保存它。
如果您刚刚创建了您的宏库,编辑器将创建一个名为NewMacro_0的新宏,并将其突出显示以便您重命名。
就像处理函数一样,您可以输入一个描述并为您的宏定义一个类别。您还可以使用实例颜色为您的宏定义一个颜色。
在下面的屏幕截图中,您可以看到我创建了一个具有多个输出的宏,并为宏定义了描述、类别和实例颜色:

在任何其他蓝图中,我现在都可以获取这个宏并使用它。如果您将鼠标悬停在宏上,您可以看到您设置的作为工具提示的描述。

接口图
接口图是函数的集合,没有任何实现,可以添加到其他蓝图中。任何实现接口的蓝图类都将肯定包含接口中的所有函数。然后,用户需要为该接口中的函数提供功能。接口编辑器类似于其他蓝图,但您不能添加新变量、编辑图表或添加任何组件。
接口用于在具有特定功能的不同蓝图之间进行通信。例如,如果玩家有一个火焰喷射器枪,在游戏中您有冰和布料,两者都可以受到伤害,但一个应该融化,另一个应该燃烧。您可以创建一个包含TakeWeaponFire函数的蓝图接口,让冰和布料实现此接口。然后,在冰蓝图中,您可以实现TakeWeaponFire函数并使冰融化,在布料蓝图中,您可以实现相同的函数并使布料燃烧。现在,当您使用火焰喷射器射击时,您只需调用TakeWeaponFire函数,它就会调用那些蓝图中的函数。
要创建一个新的接口,您需要在内容浏览器上右键单击,并从蓝图子类别中选择蓝图接口,然后命名它。
在下面的示例中,我将其命名为BP_TestInterface:

如果您刚刚创建了您的接口,编辑器将创建一个名为NewFunction_0的空白函数,该函数将突出显示以便您重命名。如果您在任何蓝图中实现此接口,则它将具有此函数。
在此示例中,我创建了一个名为MyInterfaceFunction的功能。我们将使用它简单地打印出实现此接口的 Actor 名称。

要为此函数创建功能,我们首先需要在蓝图中实现此接口。因此,打开您想要实现此功能的蓝图,并在工具栏中选择类设置。

现在,详细信息面板将显示此蓝图的相关设置,在接口部分,您可以添加您的接口。

一旦添加了该接口,我的蓝图标签页将更新以显示接口功能。现在您只需双击该功能即可打开图表并添加功能。

我的接口函数出现在我的蓝图标签页中的原因是该函数包含一个输出值。如果您有一个没有输出的接口函数,则它不会出现在我的蓝图标签页中。相反,当在蓝图上右键单击时,它将出现在事件下。例如,在同一个接口中,我创建了一个没有输出数据的另一个函数。

另一个接口函数不会出现在我的蓝图标签页中,因为它没有输出。因此,要在您的蓝图实现此函数,您必须将其添加为事件。

蓝图节点引用
使用各种节点定义蓝图对象的行为。节点可以是事件、函数调用、流程控制、变量等,这些都是在图中使用的。尽管每种类型的节点都有其独特的功能,但它们的创建和使用方式是通用的。
通过在图面内右键单击并从上下文菜单中选择节点,可以将节点添加到图中。如果选择了蓝图内的组件,则该组件支持的事件和函数也会列出。

添加节点后,您可以使用左鼠标按钮选择并移动它。您可以使用Ctrl键向当前节点选择中添加或删除节点。在图中单击并拖动会创建一个矩形选择,它将添加到当前选择中。
节点可以有多个输入和输出,分为两种类型:执行引脚和数据引脚。
执行引脚启动执行流程,当执行完成后,它会激活一个输出执行引脚以继续流程。未连接时,执行引脚以轮廓形式绘制,连接时以纯白色绘制。

数据引脚是节点,用于从一个节点传输(如取用和输出)数据到另一个节点。这些节点是类型特定的。这意味着它们可以连接到相同类型的变量。如果将它们连接到不同类型的另一个数据引脚,某些数据引脚会自动转换。例如,如果您将float变量连接到string,蓝图编辑器将自动插入一个float到string转换节点。像执行引脚一样,未连接时以轮廓形式绘制,连接时以纯色绘制。

节点颜色
蓝图中的节点有不同的颜色,表示它是什么类型的节点。
红色节点表示它是一个事件节点,这是执行开始的地方。

蓝色节点表示它可以是函数或被调用的事件。这些节点可以有多个输入或输出。函数顶部的图标将根据它是函数还是事件而改变。

紫色的节点既不能创建也不能销毁。你可以在构造脚本和函数中看到此节点。

灰色的节点可以是宏、流程控制或折叠节点。

绿色的节点通常表示一个纯函数,用于获取值。

蓝色的节点表示它是一个铸造节点。此节点将给定的对象转换为另一个对象。

变量
变量是持有值或对象引用的属性。它们可以在蓝图编辑器内部或从另一个蓝图访问。它们可以创建以包含数据类型(float、integer、Boolean等)或引用类型或类。每个变量也可以是一个数组。所有类型都有颜色编码,以便于识别。
数学表达式
数学表达式节点本质上是可以双击打开子图以查看功能的折叠节点。每次你重命名节点时,都会解析新的表达式并生成一个新的图。要重命名节点,只需选择它并按F2。
要创建一个数学表达式节点,在图编辑器上右键单击并选择添加数学表达式节点。然后你将被提示输入你的数学表达式。
例如,让我们输入这个表达式:(vector(x, y, z)) + ((a + 1) * (b + 1)) 并按Enter。

你现在会看到数学表达式节点已经自动解析了你的表达式,并从你的表达式中生成了适当的变量和图。

以下运算符受支持,可以与逻辑和比较运算符结合使用以创建复杂表达式:
-
乘法: *, /, % (取模)
-
加法: +, -
-
关系: <, >, <=, >=
-
相等性: == (等于), != (不等于)
-
逻辑: || (或), && (与), ^ (幂)
创建我们的第一个蓝图类
现在我们已经了解了蓝图是什么以及它做什么,让我们创建一个简单的蓝图演员,它会在自己的基础上旋转,并在几秒钟后通过粒子效果和声音自我销毁。创建我们的蓝图后,我们将将其拖放到世界中,并在运行游戏时使用关卡蓝图动态生成此蓝图。
创建一个新的蓝图
要创建此蓝图,首先在内容浏览器内右键单击并选择蓝图类。点击后,你将被提示选择蓝图的一个父类。你需要为你的蓝图指定一个父类,因为它将继承该父类的所有属性。
尽管你可以选择所有现有的类(甚至其他蓝图类),但让我们看看最常见的父类:
-
演员: 基于演员的蓝图可以放置或生成在关卡中
-
NPC:NPC是你可以称为的代理,你可以控制它并从控制器接收输入
-
角色:这是NPC的扩展版本,具有行走、奔跑、跳跃、蹲下等功能
-
玩家控制器:用于控制角色或NPC
-
游戏模式:这定义了正在玩的游戏
-
演员组件:这是一个可重用的组件,可以添加到任何演员上
-
场景组件:这是一个具有场景变换的组件,可以附加到其他场景组件上
在这个例子中,我们将使用演员类作为我们的父类,因为我们想将其放置在级别中并在运行时生成。因此,选择演员类,Unreal 将创建并放置你的新蓝图在内容浏览器中。双击你新创建的蓝图,这将打开蓝图编辑器。默认情况下,它应该打开视口选项卡,但如果它没有,那么只需简单地选择视口选项卡。这就是你可以看到并操作所有组件的地方。
现在我们需要一个组件,当这个蓝图生成时它会旋转。在组件选项卡中,点击添加组件并选择静态网格组件。添加组件后,将其重命名为网格组件(你可以选择任何你想要的名称,但在这个例子中,让我们选择这个名称)并注意详细信息面板已经填充了静态网格属性。
在详细信息面板中,你可以找到对应于你的组件类型的部分,在那里你可以分配要使用的资产。
但是,在这个例子中,我们不是直接在组件选项卡中分配网格,而是创建一个静态网格变量,并使用它来在图中分配网格。这样,我们可以更改网格而不必打开蓝图编辑器。
在我的蓝图选项卡中,创建一个新变量并将类型设置为静态网格(确保选择引用)。
小贴士
在 Unreal Engine 4.9 之前的版本中,你可以搜索静态网格并简单地选择引用。在 4.9 之前没有其他选项可以选择。
之后,将那个变量重命名为我的网格。由于这个变量用于将资产分配给我们的静态网格组件,让我们将其公开,以便在将其放置在世界上之后在详细信息面板中更改它。要公开这个变量,请选择它并在蓝图编辑器内部的详细信息面板中启用可编辑。在使其可编辑后,编译蓝图(快捷键:F7),你将能够为我的网格变量分配一个默认网格。对于这个例子,让我们添加一个简单的立方体静态网格。
现在我们已经设置了变量,我们可以将其分配给我们的静态网格组件。由于我们知道构造图在每次初始化此蓝图以及每次更改变量或属性时都会执行,因此我们将在这里为我们的静态网格组件分配网格。因此,打开构造图并:
-
在图表编辑器上右键单击并搜索获取网格组件。
-
从上下文菜单中选择获取网格组件。
-
从输出引脚点击并拖动,然后释放。你现在将看到一个新上下文菜单,并在该菜单中搜索设置静态网格并选择它。
-
再次在图表编辑器上右键单击并搜索获取我的网格。
-
选择获取我的网格并将输出引脚连接到设置静态网格蓝图节点的输入(新网格)。
-
最后,将构造脚本的执行引脚连接到设置静态网格蓝图节点,并按编译(快捷键:F7)。
如果你在编译后检查视口选项卡,你将看到你的新网格在那里。从这一点开始,你可以随意将这个蓝图拖到世界中,在细节面板中,你可以将我的网格更改为任何其他静态网格。
小贴士
按Ctrl+E打开您在世界中选择的对象的关联编辑器。
旋转静态网格
在蓝图编辑器中,有几种旋转网格的方法,在本节中我们将探讨最简单的方法,即使用旋转运动组件。
如果您已关闭蓝图,请将其打开并添加一个名为旋转运动的新组件。此组件将使该演员在给定的旋转速率下持续旋转,可选地围绕指定点旋转。此组件有三个主要参数可以在蓝图图中更改。它们是:
-
旋转速率:此更新翻滚/俯仰/偏航轴的速度。
-
枢轴平移:我们旋转的枢轴点。如果设置为零,则围绕对象的起点旋转。
-
局部空间中的旋转:旋转是应用于局部空间还是世界空间。
您可以创建两个新的变量(旋转器和向量变量)并将它们设置为可编辑的,这样您就可以在世界的细节面板中更改它们。最终的图表应如下所示:

在几秒钟后销毁我们的蓝图演员
一旦我们将此演员放置或生成到世界中,我们将使用粒子效果和声音销毁此演员。为此:
-
创建一个新的变量(
float)并将其命名为销毁后。让我们给它一个默认值五秒。 -
前往事件图并添加一个名为事件开始播放的新事件。当游戏开始或演员在游戏中生成时,此节点立即执行。
-
在图表编辑器上右键单击并搜索延迟并添加它。将事件开始播放连接到延迟节点。此节点用于在指定秒数后调用动作。
-
延迟节点接受一个
float值,用于持续时间。持续时间结束后,执行继续到下一个动作。我们将我们的销毁后变量连接到延迟的持续时间。 -
右键单击图并搜索在位置生成发射器。此节点将在指定的位置和旋转处生成给定的粒子效果。将Delay连接到该节点,并在发射器模板中设置一个粒子效果。要设置位置,右键单击图并搜索GetActorLocation并将其连接到位置引脚。
-
右键单击图并搜索在位置生成声音。此节点将在给定位置生成并播放声音。将Spawn Emitter节点连接到该节点。
-
最后,为了销毁此演员,右键单击图编辑器并搜索DestroyActor并将其连接到Spawn Sound节点。
最终的图应该看起来像这样:

现在,当你将这个演员放置在世界上并开始游戏时,你会看到它旋转,并在五秒钟(或你在销毁后使用的值)后,在生成粒子效果和声音后,这个演员将被销毁。
在级别蓝图中生成了我们的蓝图类
我们现在将看到如何在游戏运行时在世界上生成这个蓝图演员,而不是在编辑时直接放置。
在我们继续之前,我们将修改旋转蓝图演员中的DestroyAfter变量。打开旋转演员的蓝图编辑器,在变量中,选择DestroyAfter变量,并在详细信息面板中启用在生成时暴露设置。

此设置意味着此变量将在Spawn Actor节点中暴露。
打开你的级别,在工具栏上,点击蓝图按钮并选择打开级别蓝图。在级别蓝图中执行以下步骤:
-
右键单击图并搜索Event BeginPlay并添加它。
-
右键单击图并从类搜索Spawn Actor并添加它。此节点将在指定的位置、旋转和缩放处生成给定的演员类。
-
在类引脚设置中将类设置为我们的旋转蓝图演员。注意现在销毁后变量已经暴露给了Spawn节点。你现在可以从那个Spawn节点调整那个值。
-
从Spawn Transform节点拖动并释放左鼠标按钮。从结果上下文菜单中选择制作变换。变换节点包含 3D 变换,包括平移、旋转和缩放。对于此示例,让我们将位置设置为0,0,300,这样这个演员将在地面上方生成 300 个单位。
结果图应该看起来像这样:

如果你播放(Alt+P)或模拟(Alt+S),你会看到这个旋转的演员在地面上方生成300个单位并旋转。
摘要
在本章中,我们学习了组件是什么以及我们如何使用它们来定义蓝图演员。我们还了解了蓝图节点以及如何创建它们。从本章所学的内容中,你可以通过以下方式更进一步:
-
当在关卡中重叠放置的触发体积中生成此演员时
-
在生成此蓝图时播放粒子效果和声音效果
-
如果玩家位于某个半径内,对玩家造成伤害
在下一章中,我们将使用 Matinee 创建一个剪辑场景。
第七章。Matinee
Matinee 提供了在游戏过程中或电影游戏序列中动态地或以动态方式对演员的各种属性进行关键帧的能力。该系统基于专门的轨道,您可以在演员的某些属性上放置关键帧。Matinee 的用户界面(UI)与其他非线性视频编辑软件类似,这使得视频编辑人员更容易上手。
在本章中,我们将创建一个 Matinee 序列,并学习如何通过关卡蓝图来播放它。因此,为了开始,让我们启动 Unreal Engine 4 并基于第三人称模板创建一个新的项目。
创建一个新的 Matinee
要打开 Matinee UI,我们首先需要创建 Matinee 资产。您可以通过点击Matinee按钮并在关卡编辑器工具栏中选择添加 Matinee来创建 Matinee 资产。当您点击它时,可能会收到一个警告,说明撤销/重做数据将被重置。这是因为,当您处于 Matinee 模式时,一些更改被转换为关键帧,而编辑器需要清除撤销堆栈。点击继续,一个新的 Matinee 演员将被放置在关卡中,Matinee 编辑器将打开。让我们更详细地看看 Matinee 窗口:

创建新的 Matinee 演员
这是 Matinee 演员的图标:

世界中放置的 Matinee 演员
创建一个新的 Matinee 演员后,它将自动打开Matinee窗口。如果它没有自动打开,那么请在世界中选择Matinee 演员,然后在细节面板中点击打开 Matinee。

Matinee 窗口
让我们快速浏览一下 Matinee 窗口:

Matinee 窗口由以下部分组成:
-
工具栏:这里包含了 Matinee 编辑器中所有常用的按钮,例如播放 Matinee、停止它等等。让我们更详细地看看工具栏按钮:
-
添加关键帧:这个选项在当前选定的轨道上添加一个新的关键帧。
-
插值:这个选项设置添加新关键帧时的默认插值模式。
-
播放:这个选项从轨道视图中的当前位置以正常速度播放预览到序列的末尾。
-
循环:这个选项在循环部分循环预览。
-
停止:这个选项停止预览播放。点击两次将回放序列并放置时间条在 Matinee 的开始位置。
-
反向:这个选项反转预览播放。
-
相机:这个选项在世界上创建一个新的相机演员。
-
播放速度:这个选项调整播放速度。
-
捕捉设置:这个选项设置捕捉的时间轴比例。
-
曲线:这个选项切换曲线编辑器。
-
捕捉:这个选项切换时间光标和关键帧的捕捉。
-
时间到帧:这个功能会将时间轴光标捕捉到捕捉设置下拉菜单中选择的设置。只有当捕捉设置使用每秒帧数时,此功能才可用。
-
固定时间: 这将 Matinee 的播放锁定到快照设置中指定的帧率。只有当快照设置使用每秒帧数时才启用。
-
序列: 这将时间线视图与整个序列匹配。
-
选择: 这将时间线视图与所选键匹配。
-
循环: 这将时间线视图与循环部分匹配。
-
循环序列: 这自动将循环部分的开始和结束设置为整个序列。
-
结束: 这将移动到轨道的末尾。
-
记录: 打开Matinee 录制器窗口。
-
电影: 这允许您将 Matinee 导出为电影或图像序列。
由于 Matinee 类似于其他非线性视频编辑器,您可以使用以下常用快捷键:
-
J 播放序列向后
-
K 停止/暂停
-
L 播放序列向前
-
加号(+)用于缩进时间线
-
减号(-)用于从时间线中缩出
-
-
曲线编辑器: 这允许您可视化并编辑 Matinee 序列中轨道使用的动画曲线。这允许对随时间变化的属性进行精细控制。可以通过切换曲线按钮编辑具有动画曲线的某些轨道。点击它将曲线信息发送到曲线编辑器,在那里曲线将可见给用户。
-
轨道: 这是 Matinee 窗口的核心。这是您设置所有轨道关键帧并将它们组织到标签、组和文件夹中的地方。默认情况下,当您创建 Matinee 时,长度设置为 5 秒。
![Matinee 窗口]()
-
标签: 这些用于组织目的。您可以将您的轨道放入各种标签中。例如,您可以将所有灯光放入 Matinee 的灯光标签,相机放入相机标签,等等。所有标签将显示您序列中的所有轨道。
-
轨道列表: 这是您创建可以创建时间线关键帧的轨道并将它们组织到不同组的地方。您还可以创建新文件夹并将所有组组织到单独的文件夹中。
-
时间线信息: 这显示了关于时间线的相关信息,包括当前时间、光标位置和序列的总长度。
-
时间线: 这显示了序列中的所有轨道,这是我们在其中使用关键帧操作对象、动画相机等的地方。绿色区域显示了循环部分(在绿色标记之间)。在轨道视图底部,您可以看到一个小黑条,称为时间栏。如果您点击并按住它,您可以向前或向后刮擦时间线,这允许您快速预览动画。要调整序列的长度,请将最右侧的红标记移动到您想要此 Matinee 的长度。
-
操作对象
Matinee 可以用来创建剪辑场景,其中你可以移动摄像机和操作对象,或者它可以用于简单的游戏元素,例如开门和移动电梯。在这个例子中,我们将看到如何将一个简单的立方体从一个位置移动到另一个位置。
从引擎内容中,我们将拖放Cube网格到我们的世界中。这位于Engine Content\BasicShapes文件夹中。

要获取引擎内容,你需要在内容浏览器中启用它。
-
在内容浏览器的右下角,你可以看到视图选项。
-
点击它并启用显示引擎内容。

在我们将Cube放入世界中后,让我们打开Matinee编辑器窗口。确保在世界中选中Cube,然后在轨迹列表区域右键单击并选择添加新空组。你现在将被提示为你的组输入一个名称。让我们称它为Cube_Movement。
注意
注意,如果你在屏幕右下角看到一个通知说Cube Mobility已更改为Movable,请不要慌张。在 Matinee 中被操作的角色必须将Mobility设置为Movable。
如果你现在在 Matinee 中点击这个组,你可以看到世界中的Cube会自动为你选中。这是因为,当我们创建组时,我们在世界中选中了Cube,你在世界中选中的任何对象都会自动连接到你创建的组。
要在世界中移动立方体,我们需要向我们的Cube_Movement组添加一个运动轨迹。要创建此轨迹:
-
右键点击我们的空组(Cube_Movement)。
-
选择添加新 运动轨迹。

这将在我们的空组中添加一个新的运动轨迹,并将我们立方体的当前位置设置为第一个关键帧。

时间轴开头的三角形是关键帧。
现在,我们想让立方体向右移动一段距离,并且在这个序列结束时,它应该回到默认位置。所以让我们将时间条拖到序列的中间(因为默认长度是 5 秒,我们将时间条拖到2.5)并回到视口编辑器。在那里,我们选择并移动立方体到右侧(Y轴)并按Enter。注意,现在 Matinee 在时间槽2.5为你创建了一个新的关键帧,你将看到一个代表立方体移动路径的虚线黄色线。

要在确切的时间(例如,精确到2.5)设置关键帧,你可以左键单击关键帧以选中它,然后右键单击并选择设置时间。你现在将被提示输入设置关键帧的新时间。在这里,你可以输入并设置2.5。
如果您现在拖动时间栏,您将看到立方体从其原始位置移动到我们在时间2.5处关键帧的新位置。现在,为了在序列结束时将立方体返回到原始位置,我们可以简单地复制粘贴第一个关键帧到序列的末尾。为此,单击第一个关键帧并按Ctrl+C复制它。然后,拖动时间栏到序列的末尾并按Ctrl+V粘贴它。完成的 Matinee 应如下所示:

如果您现在在工具栏中点击播放,您将看到立方体从其原始位置移动到新位置,然后在序列结束时,它将返回到原始位置。
现在 Matinee 已经准备好了,我们将了解如何在游戏中播放 Matinee。我们要做的是在关卡中放置一个触发框,当我们的玩家重叠它时,Matinee 将播放。当我们的玩家走出触发框时,Matinee 将停止。
要在世界中放置一个触发框,您需要从模式标签页(位于体积类别的位置下)拖动它并将其放入视口。如果您没有模式标签页,那么:
-
按Shift+1打开它(确保您的视口处于焦点)。
-
在模式标签页中,进入位置模式(Shift+1)。
-
选择体积标签页。
-
拖动并放置触发体积框。

一旦触发框放置在世界中(您可以随意调整触发框的大小),右键单击它并导航到添加事件 | OnActorBeginOverlap。

这将在关卡蓝图中为我们的触发体积添加一个新的重叠事件。由于我们需要在退出触发器后停止 Matinee,我们将再次右键单击触发体积并导航到添加事件 | OnActorEndOverlap。现在我们在关卡蓝图中有两个事件(开始重叠和结束重叠)。

如您所见,这两个重叠事件都给出了当前重叠此触发体积的演员。我们将使用此信息仅在角色重叠时播放 Matinee。为此,我们必须遵循以下过程:
-
从OnActorBeginOverlap事件中的其他演员引脚点击并拖动。从生成的上下文窗口中,输入Cast to Character并选择它。
-
将OnActorBeginOverlap的执行引脚连接到我们刚刚创建的Cast节点。
-
要播放 Matinee,我们首先需要在关卡蓝图中创建它的引用。为此,在世界中选择 Matinee 图标并右键单击关卡蓝图内部。从生成的上下文窗口中,选择创建 Matinee 演员的引用。这将添加一个新的节点,该节点引用世界中的 Matinee 演员。从该节点,拖动一条新电线并输入Play并选择它。
-
将角色节点的输出(未命名)执行引脚连接到 Matinee 的播放节点。
-
要在退出触发器时停止 Matinee,你可以进行与之前相同的设置,但使用停止节点而不是播放节点。
最终的图表应该看起来像这样:

现在,当你玩游戏并重叠触发器时,我们的 Matinee 将播放。

场景镜头相机
由于你已经学会了如何创建 Matinee 并移动对象,现在是时候学习如何创建一个简单的场景剪辑了。在本节中,我们将创建一个在 Matinee 被触发时聚焦于立方体的相机。
要创建一个相机,让我们首先将视口相机定位在正确的位置。在你的编辑器视口中,导航到你想要 Matinee 相机所在的位置。在下面的屏幕截图中,你可以看看我放置相机的地方:

在导航到你的目标位置后,打开Matinee窗口。在工具栏上,点击相机按钮(这将提示你输入新的组名)以在当前的视口相机位置创建一个相机。

这也将创建一个新的相机组,包含两个轨道。它们是视野(FOV)和运动。由于我们不使用 FOV 轨道,你可以右键点击它并选择删除轨道,或者简单地按Delete键从轨道列表中移除它。
在选择相机的运动轨道后,将时间条拖动到序列的末尾。然后在编辑器视口中,选择 Matinee 创建的相机并将其移动到新的位置。在这个例子中,我将相机移动到右侧并旋转了 30 度。在下面的屏幕截图中,你可以看到相机的初始位置和序列末尾的新位置。

这是相机的新的位置:

如果你现在播放并从我们之前放置的触发体积触发 Matinee,你会看到立方体像往常一样移动,但你不会从相机视角看到它。要从我们放置的相机中看到它,你需要给你的 Matinee 添加一个导演轨道。让我们看看导演组是什么。
导演组
导演组主要功能是控制 Matinee 的视觉和音频。这个组的重要功能是控制哪个相机组被选中在序列中显示。当我们在 Matinee 中有多个相机时,我们使用这个组在相机之间切换。
要创建一个新的导演组,右键点击轨道列表并选择添加新导演组。一个新的独立组将出现在所有其他组之上。

由于我们在这个组中只有一个摄像机,我们将将其添加到我们的导演轨道中。选择导演轨道并按Enter键。一个新弹窗将询问您选择哪个轨道,因此请选择MyCamera组(这是我们使用 Matinee 工具栏中的摄像机按钮创建的组)。MyCamera这个名字是我选择的。将在导演轨道中添加一个新的关键帧,显示为MyCamera [Shot0010]。这意味着每当 Matinee 播放时,您将通过MyCamera组看到。稍后,如果您添加更多摄像机,您可以在导演组之间切换摄像机。
最终结果应该看起来像这样:

现在,如果您在游戏中播放 Matinee,您将通过新的摄像机视图看到它。

有时候,当播放过场动画时,最好禁用玩家移动(这样当过场动画处于活动状态时,所有玩家输入,如移动,都将被禁用)以及 HUD 等。要执行这些操作,请选择世界中的 Matinee 演员,然后在详细信息面板中,您可以设置必要的选项。

摘要
Matinee 是一个非常强大的工具,可以用来创建游戏中的电影。通过多个摄像机和其他视觉/音频效果,您可以创建看起来很好看且专业的电影。由于您已经学会了如何在本章中操作对象和摄像机,现在您应该尝试使用一个充当监控摄像机的摄像机来创建电梯运动。
第八章。Unreal 运动图形
Unreal 运动图形(UMG)是一个用户界面(UI)创作工具,用于创建游戏中的抬头显示(HUD)、主菜单和其他 UI 元素。它们使用一个名为小部件蓝图的特殊蓝图创建,其中包含各种预定义的小部件,您可以使用它们来构建您的界面。现在让我们看看 UMG。
在本章中,您将学习如何创建 UMG 小部件并将一个分配给我们的角色以显示其健康状态。您还将学习如何创建浮动健康条。
设置项目
要开始,启动 Unreal Engine 4 并基于第三人称模板创建一个新的项目。
由于我们将有一个带有健康条的 HUD,让我们在我们的第三人称角色蓝图中添加一个新的健康变量。在ThirdPersonBP/Blueprints文件夹中打开ThirdPersonCharacter蓝图:

在我们的角色蓝图中创建一个名为Health的新变量,并按照以下步骤操作:
-
将变量类型设置为
float并为其提供一个默认值 100。下一步是创建一个纯函数,该函数显示玩家总健康的百分比。 -
在您的角色蓝图中创建一个新的函数(例如,GetHealthPercentage)并打开它。
-
在函数图中,获取您的健康变量并将其除以健康默认值。通过这样做,我们将得到玩家健康的百分比。要获取您类中任何变量的默认值,只需在图中右键单击并搜索获取类默认值。此节点将返回您创建的所有变量的默认值。
-
现在,为这个函数创建一个新的输出(float 类型)并将结果(除法节点)连接到这个输出。这个函数现在将返回玩家健康的百分比。例如,如果玩家的健康是 42,那么除以 100(默认健康值)将返回 0.42。我们可以使用这个信息在我们的 HUD 进度条以及浮动健康条中。
生成的蓝图函数应如下所示:

注意
注意,将输出名称设置为ReturnValue非常重要。
我们现在将创建一个 UMG 小部件并利用这个函数来显示玩家的健康状态。
创建 HUD 小部件
要创建一个新的小部件蓝图:
-
右键点击内容浏览器
-
在用户界面部分下选择小部件蓝图:
![创建 HUD 小部件]()
一旦选择,新的小部件蓝图将被放置在内容浏览器中,并提示您输入一个新名称。在这个例子中,我将其命名为MyUMG_HUD。
双击MyUMG_HUD以打开它:

小部件蓝图用户界面
这就是小部件蓝图。这是您创建游戏 UI 的地方。让我们更仔细地看看小部件蓝图 UI:
-
工具栏:这是常见的工具栏,允许您编译、保存、播放和调试您的图形。
-
编辑模式:这允许您在设计器模式和图形模式之间切换。
-
视觉设计器:这是主要区域,您可以将所有小部件拖放到此处以创建您的 UI,就像它在游戏中出现的那样。
-
调色板:这是您可以拖放到视觉设计器中的小部件列表。这还将列出您创建的任何自定义小部件。
-
层次结构:这显示了此小部件的结构。您也可以在此处拖放小部件。
-
动画列表:这允许您创建新的动画轨迹,您可以使用它来动画化小部件的各种属性。
-
动画轨迹编辑器:创建新的动画后,您可以选择该动画并在此处创建关键帧。
由于我们将使用此作为我们的玩家 HUD,让我们创建一个显示玩家健康的进度条。
创建健康条
从调色板窗口,将进度条小部件拖放到视觉设计器。一旦放置在视觉设计器上,您可以将其调整到任何大小。您也可以将其放置在任何位置,但在这个例子中,我决定将其保持在屏幕的左下角。
当您选择进度条小部件时,您将在详细信息面板中看到您可以编辑的所有属性,包括您进度条的名称。在这个例子中,我已经将我们的进度条名称更改为 HealthBar。进度条小部件提供了一系列您可以更改的设置,包括外观和感觉。
以下截图是我刚刚放置的健康条:

让我们快速看一下您将更改的一些常见设置:
锚点:这些定义了小部件的位置,并保持它在不同屏幕尺寸下的位置。默认情况下,有 16 个锚点位置,通常这些中的一个就足够满足大多数需求。但有时您必须手动调整锚点位置。例如,如果您的游戏有一个玩家可以动态调整内容的库存系统,那么您需要手动调整锚点位置。在这个例子中,我们将锚点位置设置为屏幕的左下角。
-
位置 X:这将在X 轴上定位小部件。(水平)。
-
位置 Y:这将在Y 轴上定位小部件。(垂直)。
-
大小 X:这会在X 轴上缩放小部件。
-
大小 Y:这会在Y 轴上缩放小部件。
-
对齐:这是小部件的支点。将X和Y都设置为
0.0将支点设置为左上角,将两者都设置为1.0将支点设置为右下角。您可以使用对齐选项与锚点精确设置小部件到屏幕中心。例如,您可以将对齐(X和Y)设置为0.5并将锚点设置为中央,并将位置X和Y都设置为0.0。这将使您的组件正好位于屏幕中心。这可以用于设置十字准星。 -
大小到内容:如果启用,此小部件将忽略大小 X和大小 Y值,而是根据小部件内容进行缩放。例如,如果您的 小部件是一个文本块,那么它将根据给定文本的大小自动缩放。
-
ZOrder:这定义了此小部件的渲染优先级。优先级较高的组件最后渲染,这使得它们出现在其他组件之上。
-
样式:这定义了此小部件的外观和感觉。请注意,每个小部件都有自己的独特样式设置(您可以使用纹理或材质作为小部件的图像)。如果它是一个进度条小部件,那么样式类别将允许您更改进度条填充图像、背景图像和跑马灯图像。如果它是一个按钮,那么您可以根据按钮状态更改按钮的图像。例如,正常状态、悬停状态、按下状态等。
-
百分比:这使用给定的值填充进度条。范围从 0-1。在这个例子中,我们将使用我们角色的健康百分比来驱动这个值。
-
填充类型:这定义了进度条的填充方式。例如,从左到右、从右到左、从中心等。
-
是否跑马灯:这启用了跑马灯动画进度条。这意味着进度条将显示活动,但不会指示何时停止。
-
填充颜色和透明度:这定义了进度条填充图像的颜色和透明度。
现在我们知道了进度条的设置,让我们继续并将我们角色的健康百分比分配给创建的健康条。为此,首先让我们将我们的编辑器模式切换到图形模式,方法是单击顶左角的图形按钮。一旦点击,您将看到此小部件的蓝图图形编辑器。
在小部件蓝图的原型左侧,您将看到我的蓝图选项卡。正如您在蓝图章节中学到的,这是您创建变量的地方。所以让我们创建一个新的变量(我将其命名为MyCharacter)并设置我们的第三人称角色的类型。请参考以下截图:

创建完成后,返回到设计器模式并选择你的进度条。在详细信息面板中,你可以看到绑定选项靠近百分比值。当你点击它时,你会看到一个新下拉菜单,显示我们刚刚创建的MyCharacter变量。将鼠标移到它上面,你会看到我们之前创建的GetPlayerHealthPercentage函数:

一旦点击,它将从我们的角色设置健康百分比值到进度条。
注意
如果你在绑定下拉菜单中看不到你的角色变量,请确保你已经编译了小部件蓝图。
将我们的 HUD 分配给角色
现在我们已经完成了 HUD 的设置,是时候将它分配给角色了。让我们现在关闭小部件蓝图并打开第三人称角色蓝图。
在我们的角色蓝图中,打开事件图并:
-
右键单击,从出现的上下文菜单中搜索Event BeginPlay并选择它。
-
从Event BeginPlay的执行引脚拖动一条线并释放鼠标按钮。从上下文菜单中搜索Create Widget并选择它。
-
在创建小部件节点中,从类引脚中选择MyUMG_HUD。
-
从创建小部件节点的返回值拖动一条新线并释放鼠标按钮。从上下文菜单中搜索Set My Character并选择它。
-
在图编辑器中右键单击并搜索
self并选择获取对 self 的引用。将此节点连接到My Character引脚。 -
再次,从创建小部件节点的返回值拖动一条线并搜索Add to Viewport。
-
将Set My Character节点的输出执行引脚连接到Add to Viewport节点的输入执行引脚。
结果图应该看起来像这样:

现在,如果你开始玩游戏,你会看到健康条完全填满:

注意
如果你的健康条仍然是空的,请确保你已经将GetHealthPercentage的输出名称设置为ReturnValue。
为了测试它,我们可以创建一个名为DecrementHealth的新函数并创建一个类似这样的图:

之后,从你的我的蓝图选项卡拖放此函数并将其连接到Add to Viewport节点之后。现在,如果你开始玩游戏,你会看到玩家健康值随机下降。
创建浮动健康条
在本节中,你将学习如何创建位于角色头顶上方的浮动健康条。让我们回到内容浏览器并创建一个新的小部件蓝图(例如,我将命名为MyFloatingHealthbar)并打开它。
在设计器选项卡中,你可以看到在视觉设计器的右上角有一个名为填满屏幕的选项。点击它并将它更改为自定义:

Custom模式将允许你分配此小部件的宽度和高度。让我们将宽度和高度设置为 256 和 32。现在,我们将一个新的进度条拖放到视觉设计器中,并使用以下设置:

将Anchors设置为最后一个锚点(这是填充锚点)。锚点有助于小部件在不同屏幕尺寸下保持其位置,从而避免小部件被裁剪掉屏幕。除了填充锚点之外,还有其他预设的锚点,例如填充左下角、填充右侧、填充底部区域、填充顶部区域、顶部左、中心、右角,等等。根据小部件的位置,你可以选择任何你想要的锚点,在游戏中,小部件将相对于锚点位置进行定位。
在这个例子中,由于我们设置了锚点为填充,位置 X 和 Y 以及大小 X 和 Y 将被分别替换为Offset Left、Top、Right和Bottom。将Offset Right和Bottom更改为0.0。进度条现在将正确地拉伸到视觉设计器的宽度和高度。
现在,让我们创建一个新的变量名为My Character,类型设置为你的ThirdPersonCharacter Blueprint,并将Percent值绑定到角色的GetHealthPercentage函数上。这正是我们为我们的 HUD Widget 执行的确切步骤。
设置百分比值后,现在让我们暂时关闭这个Widget Blueprint,并打开ThirdPersonCharacter Blueprint。切换到Viewport标签页,在Components标签页中点击Add Component,并选择Widget Component:

一旦选择,这个小部件组件将被添加到你的玩家角色中。选择新添加的Widget Component,在Details Panel中,将Draw Size设置为与我们用于MyFloatingHealthbar相同的尺寸,即256和32。然后设置Widget Class为MyFloatingHealthbar类,并将Space设置为Screen。最后,将Widget移动到你的期望位置。在这个例子中,我将它设置在角色的头顶上方。
仅供参考,以下是截图:

如果你现在开始游戏,你会看到生命条漂浮在玩家头顶上方,但它将是空的。这是因为我们还没有将My Character值分配给我们的浮动生命条。为了使其工作:
-
切换到Construction Script标签页。
-
在Construction Script标签页的任何位置右键单击,搜索Get Widget,并选择它。
-
从你刚刚创建的Widget节点拖动一根新线,搜索Get User Widget Object,并选择它。
-
从Get User Widget Object的返回值引脚拖动一根新线,搜索Cast到MyFloatingHealthbar,并选择它。
-
将Construction Script的输出执行引脚连接到这个新创建的Cast节点。
-
从输出引脚(例如My Floating Healthbar)拖动一根新线,搜索Set My Character并选择它。
-
将Cast节点的未命名输出执行引脚连接到Set My Character节点。
-
在图表编辑器上右键点击,搜索
self,并选择获取 self 的引用。将此节点连接到My Character引脚。
就这些了!现在如果你按播放,你将看到你的角色的生命条在你的玩家头上浮动:

摘要
UMG 可以用来创建各种 UI 效果。从这里,你可以通过添加玩家头像图像到你的浮动生命条旁边或给你的角色一个武器并显示该武器的弹药计数等方式来扩展它。你还可以将 Widget 组件添加到游戏中的其他角色(例如,宝箱)上,以显示有关该角色的信息。记住,在视觉设计器中布局你的 UI 只是开始。为了使你的 UI 看起来更好,你必须通过更改小部件的样式来改变其外观和感觉。
第九章。粒子
在虚幻引擎 4 中,粒子是通过级联粒子编辑器创建的,这是一个强大且稳健的编辑器,允许艺术家创建视觉效果。级联编辑器允许您添加和编辑构成最终效果的各个模块。粒子编辑器的主要任务是控制粒子系统的行为,而外观和感觉通常由材质控制。
在本章中,您将了解级联粒子编辑器并创建一个简单的粒子系统。
级联粒子编辑器
要访问级联粒子编辑器,您需要在内容浏览器中通过右键单击内容浏览器并选择粒子系统来创建一个粒子系统。选择它后,将创建一个新的粒子系统,并提示您重命名。给它一个名字,然后双击它以打开级联粒子编辑器。
一旦打开,您将看到一个类似这样的窗口:

级联编辑器用户界面
级联粒子编辑器由五个主要区域组成,它们是:
-
工具栏:这包含可视化和导航工具
-
视口:这显示当前粒子系统
-
详细信息:这允许您编辑当前粒子系统、发射器或模块
-
发射器:这些是实际的粒子发射器,并包含与发射器关联的模块
-
曲线编辑器:这是允许您在相对或绝对时间内修改属性的编辑器
工具栏
工具栏包含各种按钮。让我们快速看一下它们:
-
保存:这保存粒子系统
-
在 CB 中查找:这将在内容浏览器中定位当前粒子系统
-
重启模拟:这重启(重置)当前模拟
-
重启级别:这与重启模拟相同,但还会更新放置在级别中的所有实例
-
缩略图:这会将视口视图保存为内容浏览器的缩略图
-
边界:这启用或禁用粒子边界的渲染
-
原点轴:这在视口中显示原点轴
-
重新生成 LOD:点击此按钮将生成最低 LOD,复制最高 LOD
-
重新生成 LOD:点击此按钮将使用基于最高 LOD 的值生成最低 LOD
-
最低 LOD:这切换到最低 LOD
-
更低 LOD:这切换到下一个最低 LOD
-
添加 LOD:在当前 LOD 之前添加一个新的 LOD
-
添加 LOD:在当前 LOD 之后添加一个新的 LOD
-
更高 LOD:这选择一个更高的 LOD
-
最高 LOD:这选择最高 LOD
-
删除 LOD:这删除当前 LOD
LODs(细节级别)是更新粒子效果以根据玩家距离使用高效屏幕空间的方法。根据效果,粒子系统中可能有模块在玩家距离较远时太小而无法渲染。想象一下火炭。如果玩家距离较远,粒子系统仍然会处理和计算这些我们不需要的效果。这就是我们使用 LOD 的地方。细节级别(LODs)可以根据玩家距离关闭特定的模块甚至关闭发射器。
视口
视口显示了粒子系统以及其他实时更改,例如总粒子数、边界等。在左上角,您可以单击视图按钮以在未发光、纹理密度、线框模式等不同视图模式之间切换。
导航
使用以下鼠标按钮可以在视口内部进行导航:
-
左鼠标按钮:此功能用于在粒子系统中移动相机。
-
中鼠标按钮:此功能用于平移相机。
-
右鼠标按钮:此功能用于旋转相机。
-
Alt + 左鼠标按钮:此功能使粒子系统围绕中心旋转。
-
Alt + 右鼠标按钮:此功能使相机从粒子系统向前或向后移动。
-
F:此功能专注于粒子系统。
-
左键 + L 键:此功能旋转灯光,并且仅影响使用发光材质的粒子。非发光材质无效果。
在视口内部,您可以播放/暂停粒子模拟以及调整模拟速度。您可以在视口下的时间选项中访问这些设置。

详情
详情面板由当前选定的模块或发射器填充。可以通过在发射器面板中选择“无”或通过在发射器列表上右键单击并导航到粒子系统 | 选择粒子系统来访问粒子系统的主要属性。

发射器
发射器面板是粒子系统的核心,包含所有发射器的水平排列。在每个发射器列中,您可以添加不同的模块以改变粒子的外观和感觉。您可以添加任意数量的发射器,每个发射器将处理最终效果的不同方面。

发射器包含三个主要区域,具体如下:
-
在发射器块上方是发射器的主要属性,例如名称、类型等。您可以通过双击灰色区域来折叠或展开发射器列。
-
在下面,您可以定义发射器的类型。如果您将其留空(如前一张截图所示),则粒子将在 CPU 上模拟。
-
最后,您可以添加模块来定义粒子的外观。
发射器类型
级联编辑器有四种不同的发射器类型,具体如下:
-
光束类型: 当使用此类型时,粒子将输出连接两个点的光束。这意味着您必须定义一个源点(例如,发射器本身)和一个目标点(例如,一个演员)。
-
GPU 精灵: 使用此类型可以让您在 GPU 上模拟粒子。使用此发射器可以让您高效地模拟和渲染成千上万的粒子。
-
网格类型: 当使用此选项时,粒子将使用实际的静态网格实例。这对于模拟破坏效果(例如,碎片)非常有用。
-
带状物: 这种类型表示粒子应该像一条尾巴。这意味着,所有粒子(按照它们的出生顺序)都相互连接,形成带状物。
曲线编辑器
这是标准的曲线编辑器,允许用户调整粒子在其生命周期内或发射器生命周期内需要更改的任何值。要了解更多关于曲线编辑器的信息,您可以访问官方文档,网址为docs.unrealengine.com/latest/INT/Engine/UI/CurveEditor/index.html。
创建简单的粒子系统
要创建一个粒子系统:
-
右键单击内容浏览器。
-
从结果上下文菜单中选择粒子。
-
在内容浏览器中创建一个新的粒子系统资产,并提示您重命名它。
-
在这个例子中,让我们称它为MyExampleParticleSystem。
-
现在,双击它以打开粒子编辑器。
默认情况下,虚幻引擎为您创建了一个默认的发射器,以便您可以使用。这个发射器包含六个模块,它们是:
-
必需: 这包含发射器所需的所有属性,例如用于渲染的材料、发射器在循环之前应运行多长时间、此发射器是否可以循环等。您不能删除此模块。
-
生成: 此模块包含确定粒子如何生成的属性。例如,每秒生成多少粒子。您不能删除此模块。
-
生命周期: 这是生成粒子的生命周期。
-
初始大小: 这设置粒子生成时的初始大小。要修改生成后的大小,请使用大小随生命周期或大小随速度。
-
初始速度: 这设置粒子生成时的初始速度(速度)。要修改生成后的速度,请使用速度/生命周期。
-
颜色随生命周期变化: 这将设置粒子在其生命周期内的颜色。
在这个例子中,我们将修改现有的发射器,使其成为一个看起来像火花的光照粒子系统。我们还将添加碰撞,以便我们的粒子与世界发生碰撞。
创建简单的材料
在我们开始处理粒子之前,我们需要创建一个简单的材料,我们可以将其应用于粒子。要创建一个新的材料:
-
右键单击内容浏览器并选择材料。您可以随意命名它。
-
打开材质编辑器,将混合模式更改为半透明。这是必需的,因为 GPU 粒子碰撞不会在不透明材质上工作。
-
然后,将着色模型更改为不发光。这是因为我们不希望火花受到任何类型的光的影响,因为它们是自发光的。
-
最后,创建一个这样的图表:
![创建简单材质]()
注意
注意,纹理样本节点中的圆形渐变纹理是引擎本身自带的。它被称为灰度。
现在我们有了我们的材质,是时候定制我们的粒子系统了:
-
选择必需模块,并在发射器组下应用之前步骤中创建的材质。
-
右键点击发射器下方的黑色区域,然后在类型数据下选择新 GPU 精灵。这将使我们的发射器在 GPU 上模拟粒子。
![创建简单材质]()
-
选择生成模块,并在生成组下将速率设置为0。这是因为我们不想每秒生成一定数量的粒子,而是想在单帧中爆发数百个。
-
在爆发组下,在爆发列表中添加一个新条目,并将数量设置为100,将数量低设置为10。这将选择一个介于100和10之间的随机值,并生成那么多粒子。
最终的生成设置将看起来像这样:
![创建简单材质]()
-
调整生成设置后,我们将粒子的生命周期设置为0.4和3.0,因此每个生成的粒子的生命周期在0.4和3.0之间。现在我们已经有了粒子生成,是时候调整它们的大小了。为此,选择初始大小模块,并将最大值设置为1.0、10.0、0.0,将最小值设置为0.5、8.0、0.0。
![创建简单材质]()
注意
注意,由于 GPU 精灵是 2D 的,您可以忽略Z值。这就是为什么我们将它们设置为0.0。
-
之后,选择初始速度模块,并将最大值设置为100.0、200.0、200.0,将最小值设置为-100.0、-10.0、100.0。
-
现在,如果您将这个粒子拖放到世界中,您将看到粒子爆发到空中。
注意
注意,如果您没有看到任何动作发生,请确保编辑器的实时选项已开启(Ctrl+R)。

添加重力
为了使事情更加逼真,我们将对这些粒子模拟重力。回到您的粒子编辑器,按照以下步骤操作:
-
右键点击模块区域。
-
从加速度菜单中选择恒定加速度。此模块将给现有粒子的加速度添加给定的加速度,并更新当前和基本速度。
![添加重力]()
-
对于加速度值,使用0.0、0.0、-450.0。Z 轴的负值(即-450)将使粒子向下移动,就像它们受到重力的影响一样。
注意
注意,默认的重力值是-980.0。你也可以尝试这个值。
现在,如果你查看世界中的粒子,你可以看到它们向下移动,就像它们受到重力的影响一样。

应用颜色覆盖生命模块
现在我们有了类似火花的东西,让我们给它应用一些颜色。选择颜色覆盖生命模块并应用以下设置:

颜色覆盖生命是一个曲线值。这意味着你可以在粒子的生命周期中的某个点定义要应用的颜色。0.0值是开始,1.0是结束。在上面的截图中,你可以看到我在粒子生成时(In Val = 0.0)应用了明亮的橙红色(50.0,20.0,8.0),并在结束时(In Val = 1.0)应用了明亮的白色。
添加碰撞模块
要完成这个效果,我们将添加一个碰撞模块,以便我们的粒子可以与世界碰撞。要添加碰撞模块,请按照以下步骤操作:
-
在模块区域右键单击并从碰撞菜单中选择碰撞。
-
选择碰撞模块。
-
将韧性值设置为0.25。这将使碰撞的粒子弹性更小。更高的韧性意味着弹性更大的粒子。
-
将摩擦设置为0.2。这将使粒子粘附在地面上。更高的摩擦值(1.0)将使粒子在碰撞后无法移动,而较低的值使粒子在表面上滑动。
现在,如果你在这个世界中模拟或播放带有这个粒子的游戏,你可以看到它爆炸并与世界碰撞,但它非常不真实。你可以很容易地注意到每秒钟这个粒子都在重复。因此,为了防止这种情况,请按照以下步骤操作:
-
打开粒子编辑器。
-
选择必需模块。
-
在持续时间设置下,将发射器循环设置为1。默认情况下,这设置为0,意味着它将无限循环。
![添加碰撞模块]()
在蓝图中播放粒子
现在我们已经准备好了粒子效果,让我们使用蓝图来播放它:
-
在内容浏览器上右键单击。
-
选择蓝图类。
-
从结果窗口中选择Actor。
-
双击蓝图以打开编辑器。
-
在内容浏览器中选择你的爆炸粒子。
-
打开蓝图编辑器并添加一个新的粒子系统组件(如果你在内容浏览器中选择粒子,它将自动将该粒子设置为粒子系统组件的模板)。
-
切换到事件图标签页。
-
在图上任何位置右键单击,并从添加事件类别中选择添加自定义事件…。
![在蓝图中播放粒子]()
-
将该自定义事件重命名为你喜欢的任何名称。在这个例子中,我将其重命名为ActivateParticle。
-
创建一个类似这样的图:
![在蓝图中播放粒子]()
这个蓝图将在游戏开始时以及事件执行时首先执行ActivateParticle,当事件执行时,它会在0.2和2秒之间随机选择一个时间(以秒为单位)。当时间结束时,它激活粒子并再次调用此事件。
现在,如果你将这个粒子拖放到世界中并开始播放,你会看到粒子随机爆发:

摘要
从这里,你可以扩展这个粒子并添加一些灯光,使其看起来更加逼真。请注意,灯光模块不能与 GPU 粒子一起使用,因此你需要创建另一个发射器并在那里添加灯光模块。既然你已经了解了 GPU 粒子数据类型,你可以添加更多使用其他数据类型的发射器,例如光束类型、网格类型、带状类型等等。从本章和其他章节中学到的知识,你可以创建一个蓝图,其中包含一个灯光网格,当它受到伤害时会发射这种火花粒子效果。
在下一章中,我们将深入探索 C++的世界。
第十章。Unreal C++ 简介
在 第六章 蓝图 中,你学习了关于蓝图的内容,这是 Unreal Engine 4 的可视化脚本语言。现在你将学习 C++,它可以用来为蓝图创建基类。在本章中,你将学习如何创建一个 C++ 项目(我们将使用 第三人称模板)并修改它以添加对角色健康和健康恢复的支持。你还将学习如何将变量和函数暴露给蓝图。
本章将专注于在 Microsoft Windows 中使用 Visual Studio 2015 编写 C++ 代码。
设置 Visual Studio 2015
使用 Unreal Engine 4.10 时,您需要 Visual Studio 2015 来编译项目的 C++ 代码。Visual Studio 有三个版本可供选择。它们是:
-
社区版:对于任何个人和非企业组织,最多五名用户免费。对于这本书,我将使用这个版本。
-
专业版:这是一个付费版本,适用于小型团队。
-
企业版:适用于任何规模和复杂性的项目的大型团队。
您可以从 www.visualstudio.com/downloads/download-visual-studio-vs 下载 Visual Studio 2015 社区版。
访问上述链接后,选择 Community 2015 并选择您的格式进行下载。您可以下载网络安装程序或离线安装程序。要下载离线安装程序,请选择 ISO 格式:

下载设置文件后,双击 vs_community.exe 运行设置并安装 Visual Studio 2015。
注意
在安装 Visual Studio 2015 之前,请确保在 编程语言 部分选择 Visual C++。这是与 Unreal Engine 4 一起工作的必要条件。

安装完成后,设置程序将提示您重新启动计算机。这样做,您就可以使用 Unreal Engine 4 C++ 了。
工作流程改进
为了使 Visual Studio 2015 与 Unreal Engine 4 一起工作并提高开发者的整体用户体验,有一些推荐的设置。其中一些包括:
-
关闭 显示非活动块。如果不关闭,许多代码块可能会在文本编辑器中显示为灰色。(工具 | 选项 | 文本编辑器 | C/C++ | 视图)。
-
将 禁用外部依赖文件夹 设置为 True 以在 解决方案资源管理器 中隐藏不必要的文件夹。(工具 | 选项 | 文本编辑器 | C/C++ | 高级)。
-
关闭 编辑并继续 功能。(工具 | 选项 | 调试 | 编辑 并点击 继续)。
-
启用 IntelliSense。
创建 C++ 项目
现在我们已经安装了 Visual Studio,让我们创建一个包含 C++ 代码的项目。在这个项目中,我们将扩展 Unreal Engine 4 附带的三人称模板,并添加对健康(包括健康恢复)的支持:

启动 Unreal Engine 4,当项目浏览器对话框出现时:
-
选择 新建项目 选项卡
-
选择 C++ 子选项卡
-
选择 第三人称
-
命名您的项目
-
点击 创建项目
当您点击 创建项目 时,Unreal Engine 4 将创建所有必需的基本类,并为您编译项目。这可能需要一分钟或更长时间。一旦完成,您的项目解决方案文件(Visual Studio 文件)将自动打开,同时打开项目。
一旦项目打开,您可能会注意到的一个主要变化是在 工具栏 上出现了一个新的 编译 按钮。这只会出现在您的项目是代码项目的情况下:

这用于重新编译代码更改并在玩游戏时即时重新加载它们!这个系统被称为 热重载。作为程序员,您将广泛使用这个功能。
角色类
在这个项目中,我们已经有了一个角色类和一个游戏模式类可用。让我们快速看看角色类是如何制作的。
基本上,我们有一个源文件(扩展名为 .cpp)和一个头文件(.h)。简而言之,头文件包含所有声明,源文件包含这些声明的定义。要访问另一个文件中的特定方法(或函数),我们使用 # include ExampleHeader.h。这样,我们将能够访问在该头文件中声明的所有函数。
在另一个头文件中访问声明基于访问说明符。我们将在本章后面了解更多关于它们的内容。
要从 Unreal Engine 4 打开源文件(.cpp)和头文件(.h):
-
打开 内容浏览器
-
前往 C++ 类
-
选择您的项目名称文件夹
-
双击您的角色类
这将在 Visual Studio 中打开源文件(.cpp)和头文件(.h):

上一张截图显示了我们的角色类的头文件。让我们逐行分析它。
-
#pragma once:任何以井号(#)开头的行称为预处理器指令。将其视为在编译任何实际代码之前由编译器运行的指令。它们以井号(#)开头,通常以新行结束。您可以使用反斜杠(\)进行多行。在这种情况下,#pragma once是一个预处理器,其任务是防止多次包含。#pragma once也称为头文件保护。 -
#include:在这个文件中,我们看到两个包含文件。一个是来自GameFramework文件夹的Character.h(位于UE4目录中),另一个是generated.h文件:-
Character.h: 包含这个文件是因为我们的角色类是从 Unreal Engine 4 中提供的ACharacter类继承而来的。这个包含是必须的,以便访问Character类中的所有声明。 -
generated.h: 这是由 Unreal Header Tool (UHT)自动为你生成的。这些文件在你声明了USTRUCT()或UCLASS()宏时生成。它们包含了你的头文件中类型声明的详细信息。这应该是你头文件中的最后一个包含文件。
-
-
Macros:Macros也是一种预处理指令,以#define开头。在编译时间之前,编译器会将实际值复制并粘贴到使用此宏的任何地方。例如,如果你创建了一个这样的宏:#define MyMacro 3.14,那么3.14将被复制并粘贴到使用MyMacro的任何地方。 -
UCLASS(config=game): 这是一个 Unreal 宏,它使编辑器知道新的类。在括号内,你指定类修饰符和元数据。在这个例子中,我们指定了配置修饰符。这表示这个类允许在给定的配置文件中存储数据。在这种情况下,你的配置文件名将是YourGameNameGame.ini。 -
class APACKT_CPPCharacter:public ACharacter: 这表示类名,并显示了我们从哪个类继承了这个类。对于这个类,我们是从Character类继承的。 -
GENERATED_BODY(): 这是一个必须放在类体非常开始的宏。在编译时,Unreal 会将其替换为所有必要的样板代码。这意味着在编译时间之前,GENERATED_BODY()被替换为实际的代码。由于这段代码是编译类所必需的,Epic 通过创建这个宏使我们更容易做到这一点。 -
private,public, 和protected: 这些被称为访问修饰符。访问修饰符允许你决定一个方法是否可以被其他文件访问。有三种类型的访问修饰符。它们是:-
private: 这意味着你只能在类内部访问成员。在这个例子中,CameraBoom和FollowCamera被设置为私有属性。这意味着你只能在类内部访问它们。如果你创建一个新的从该类派生的类,你将无法访问它们。 -
public: 这意味着所有成员都可以从任何其他类中访问。 -
protected: 这意味着所有成员都可以从这个类及其派生类中访问。
-
-
UPROPERTY(): 这定义了属性元数据和修饰符。这些用于在属性上序列化、复制并将它们暴露给蓝图。你可以使用许多UPROPERTY ()修饰符。要查看完整列表,请访问此链接:docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Reference/Properties/Specifiers/index.html。 -
void:这意味着它是一个不返回任何数据类型的函数。一个函数可以返回任何类型的数据,如float、int、bool,甚至对象,但并不总是需要数据类型。在这种情况下,你会使用 void 返回类型来表示此方法不返回任何类型的数据。这也可以防止在子类中覆盖函数。如果你想覆盖子类中的函数,那么你需要将其设置为 virtual void。当你创建一个 virtual void 时,这意味着子类可以覆盖此函数,实现自己的逻辑,并可选地使用关键字Super调用父类函数。
理解前面的内容(预处理程序、宏、访问说明符等)将有助于你在 Unreal C++ 中工作。
另一个值得提及的是双冒号(::)、连字符箭头(->)和点(.)的使用。理解它们是什么以及如何使用它们是至关重要的。在这些中,我们主要使用连字符箭头(->)符号。让我们看看它们是什么。
-
双冒号 (
::): 当使用此符号时,意味着你正在访问特定命名空间或作用域中的方法。例如,当你想要从其他类中调用静态方法时,你会使用此符号。 -
连字符箭头 (
->): 当你指向可能在内存中某个地方存在或不存在的数据时使用。使用此符号意味着你正在尝试访问一个指针。指针指向内存中某个位置,该位置存储了该指针的实际数据。在访问指针之前,始终检查它们并确保它们是有效的。指针是 Unreal C++ 中最重要的部分之一,所以我强烈建议阅读 Nathan Iyer (Rama) 提供的这篇文章:wiki.unrealengine.com/Entry_Level_Guide_to_UE4_C%2B%2B#Pointers -
点 (.): 这用于访问数据本身。例如,你将使用它来访问结构体内的数据。
添加生命值系统
现在我们已经了解了 Character 类,让我们开始修改我们的角色,以添加对生命值和生命值恢复系统的支持。在我们开始之前,让我们快速了解一下我们将要做什么。在这个系统中:
-
一个
float变量,用于存储游戏开始时玩家的当前生命值。我们将确保当玩家初始化时,玩家拥有最大生命值。 -
覆盖
Actor类的默认函数TakeDamage ()。 -
当玩家受到伤害时,我们将检查受到的伤害量,并从生命值中减去这个数值。然后我们将启动一个计时器,该计时器将执行一个恢复生命值的事件。
创建一个生命值变量
那么,让我们开始吧。打开你的角色源文件,并在私有访问说明符下添加以下代码:
UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "My Character", meta = (AllowPrivateAccess = "true") )
float Health;
在这里,我们声明了一个 Health 变量,其数据类型为 float。我们还为我们的 float 变量添加了 UPROPERTY 并添加了 EditAnywhere、BlueprintReadWrite 和 Category 修饰符。EditAnywhere 修饰符允许你在 Details 面板中编辑这个属性。BlueprintReadWrite 允许你在 Blueprint 中获取或设置这个值。无论你将什么名字作为类别,它都会出现在 Details 面板中。如果你编译并启动你的游戏,查看 ThirdPersonCharacter Blueprint 的 Details 面板(在 ThirdPersonCPP/Blueprints 中),你会看到我们新暴露的属性:

如你所见,0.0 的值对 Health 来说没有意义。所以我们将打开我们角色类的源文件,并在类 constructor 下输入以下行:
Health = 100.f; // .f is optional. If it's confusing you can replace it with 100.0
constructor 类通常是源文件中的第一个定义。它看起来像 YourClassName::YourClassName()。
注意
任何以 //(双斜杠)开头的一行都是注释,并且会被编译器忽略。
constructor 类基本上是我们设置类默认值的地方。在这种情况下,我们希望玩家的默认健康值为 100。
现在,如果你在 Unreal Engine 编辑器中按下 Compile 按钮,编辑器将编译新的更改,并在完成后进行热重载。当编译完成后,你应该看到 health 的默认值(100)。
受伤
现在我们已经设置了健康值,我们可以在我们的 character 类中访问并更改它。我们现在需要在我们玩家受到伤害时更新这个值。由于我们的角色是 Actor 类,我们可以使用 TakeDamage() 函数来更新健康值。要做到这一点,请将以下代码添加到你的角色头文件中:
virtual float TakeDamage( float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser ) override;
注意
TakeDamage 是 Actor 类中已经存在的一个虚拟函数。所以当你想在虚拟函数中实现自定义逻辑时,确保为它们包含一个 override 关键字。这样你就告诉编译器在父类中查找这个函数的定义。如果找不到基类定义或者它已经被修改,编译器将抛出一个错误。记住,如果没有 override 关键字,编译器将把它视为一个新的定义。
TakeDamage 函数接受一些参数并返回一个 float 类型的值,这是实际造成的伤害。在这个函数中,我们首先检查我们的健康值是否大于 0。如果是,我们将 Health 值减少 Damage 值。如果不是,我们则直接返回 0:
float APACKT_CPPCharacter::TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
// Super key word is used here to call the actual TakeDamage function from the parent class which returns a float value.We then assign this value to ActualDamage which is a float type.
const float ActualDamage = Super::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);
// Check if we have health
if (Health > 0.0)
{
// Reduce health by the damage received
Health = Health - ActualDamage;
// return the actual damage received
return ActualDamage;
}
// Player has no health. So return 0.0
return 0.0;
}
在前面的示例中,你可以看到注释的使用以及它如何有助于以后阅读代码。TakeDamage 函数首先调用父类函数,该函数返回要应用的实际伤害。我们将此值保存到名为 ActualDamage 的局部变量中。然后我们检查 health 值是否大于 0.0,如果是,则通过 ActualDamage float 变量减少 health 值并返回该值。每次你重写一个虚函数并实现自定义逻辑时,你使用 Super::FunctionName() 来继承父类的基本功能。由于 TakeDamage() 函数是虚函数,并且我们重写了该函数,因此我们使用 Super::TakeDamage() 来调用在父类中定义的实际函数,该函数执行对演员应用伤害的逻辑。
生命恢复
现在我们知道我们的角色可以受到伤害,我们将进一步修改这个系统并添加生命恢复。我们的生命恢复系统将基于默认设置为每 1 秒恢复 1.0 的 float 变量来恢复生命值,这个值也设置为 float 变量。这些设置将公开到蓝图编辑器,这样我们可以在不重新编译游戏的情况下稍后更改它们。
让我们快速看一下生命恢复系统:
-
我们使用计时器来恢复生命值。
-
当玩家受到伤害时,我们将清除这个计时器。
-
在受到伤害后,我们将计时器设置为 2 秒后重启。计时器将调用一个自定义函数来恢复生命值。
-
当计时器结束时,它将调用自定义事件,增加 1 点生命值。这个计时器将持续运行,直到玩家达到最大生命值。
因此,我们首先需要的是一个 TimerHandle。这有助于识别绑定有相同方法的 Timers。要声明 TimerHandle,打开角色头文件,并在 GENERATED_BODY () 下添加以下行:
FTimerHandle TimerHandle_HealthRegen;
注意
你可以为 TimerHandle 使用任何名称。在这里,在 HealthRegen 前使用 _TimerHandle 是可选的。
既然我们知道我们将使用计时器,那么让我们添加两个新的 float 变量,它们将作为激活 RegenerateHealth 函数的时间:
-
我们将第一个
float变量命名为InitialDelay。这个变量用于在受到伤害后调用RegenerateHealth。我们将默认值设置为2。 -
我们将第二个
float变量命名为RegenDelay。当从TakeDamage函数开始恢复时,我们使用这个RegenDelay时间再次调用RegenerateHealth函数。我们将默认值设置为0.5。
以下是一些变量:
/* After taking damage, Regenerate Health will be called after this much seconds. */
UPROPERTY( EditAnywhere, Category = "My Character" )
float InitialDelay;
/* Time to regenerate health. */
UPROPERTY( EditAnywhere, Category = "My Character" )
float RegenDelay;
我们还将添加一个名为 RegenerateAmount 的新属性,并将其公开到蓝图编辑器:
UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "My Character", meta = (AllowPrivateAccess = "true") )
float RegenerateAmount;
在RegenerateAmount变量中,你可以看到一个名为AllowPrivateAccess的新元指定符。当你想在私有访问指定符中有一个变量,但同时也需要在蓝图中使用它(BlueprintReadOnly或BlueprintReadWrite)时,会用到这个指定符。如果没有AllowPrivateAccess,当你在私有访问指定符下的变量上使用BlueprintReadWrite或BlueprintReadOnly时,编译器将抛出错误。最后,我们将添加一个名为RegenerateHealth的新函数,如下所示:
void RegenerateHealth();
目前,我们已经完成了头文件的修改。让我们打开角色源文件,并在类构造函数(记住类构造函数是YourClassName::YourClassName())中添加RegenerateAmount的默认值1.0。
注意
constructor类在蓝图中不是构造脚本。如果你想在 C++中实现构造脚本行为,你需要重写OnConstruction方法。
我们还将像这样将RegenerateHealth函数添加到我们的源文件中:
void APACKT_CPPCharacter::RegenerateHealth()
{
}
在这个函数内部,我们将编写我们的代码,将RegenerateAmount值添加到我们现有的健康值中。所以让我们修改如下:
void APACKT_CPPCharacter::RegenerateHealth()
{
if (Health >= GetClass()->GetDefaultObject<ABaseCharacter>()->Health)
{
Health = GetClass()->GetDefaultObject<ABaseCharacter>()->Health;
}
else
{
Health += RegenerateAmount;
FTimerHandle TimerHandle_ReRunRegenerateHealth;
GetWorldTimerManager().SetTimer( TimerHandle_ ReRunRegenerateHealth, this, &APACKT_CPPCharacter::RegenerateHealth, RegenDelay );
}
}
现在,让我们分析一下这段代码。在这个函数内部,我们首先做的事情是检查我们的Health是否大于或等于我们的默认Health。如果是,我们只需将健康值设置为默认值(这是我们在构造函数中设置的)。如果不是,我们向现有的健康值添加RegenerateAmount,并使用计时器重新运行此函数。
最后,我们修改TakeDamage函数以添加HealthRegeneration:
float APACKT_CPPCharacter::TakeDamage( float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser )
{
// Get the actual damage applied
const float ActualDamage = Super::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);
if (Health <= 0.0)
{
// Player has no health. So return 0.0
return 0.0;
}
// Reduce health by the damage received
Health = Health - ActualDamage;
//Is the health reduced to 0 for the first time?
if (Health <= 0.0)
{
// Clear existing timer
GetWorldTimerManager().ClearTimer(TimerHandle_HealthRegen);
return 0.0;
}
// Set a timer to call Regenerate Health function, if it is not running already
if (!GetWorldTimerManager().IsTimerActive(TimerHandle_HealthRegen))
{
GetWorldTimerManager().SetTimer(TimerHandle_HealthRegen, this, &APACKT_CPPCharacter::RegenerateHealth, InitialDelay);
}
// return the actual damage received
return ActualDamage;
}
在上面的代码中,我们首先检查我们的健康值是否小于或等于0.0。如果是,那么我们知道玩家没有健康值,所以我们只需简单地返回0.0。否则,我们减少我们的health值,并检查健康是否小于或等于0。如果健康值为0,我们清除计时器,否则我们检查健康恢复是否当前处于活动状态。如果它不活跃,那么我们创建一个新的计时器来运行RegenerateHealth函数,最后返回应用的ActualDamage。
C++ 到 蓝图
我们现在在我们的角色类中有一个健康和健康恢复系统。我们当前系统的一个问题是,我们还没有定义当健康值达到 0 时我们的角色会发生什么。在本节中,我们将创建一个事件,我们将在蓝图(Blueprint)中实现这个事件。当玩家的健康值达到 0.0 时,将调用此事件。要创建此蓝图事件,打开我们的角色头文件,并添加以下代码:
UFUNCTION(BlueprintImplementableEvent, Category = "My Character")
void PlayerHealthIsZero();
正如你所见,我们添加了一个名为PlayerHealthIsZero()的普通函数。为了使其在蓝图(Blueprint)中可用,我们添加了UFUNCTION指定符,并在其中添加了BlueprintImplementableEvent。这意味着 C++可以调用这个函数,它将在蓝图内部执行,但我们不能在我们的角色源文件中为这个函数添加定义。相反,我们将在源文件中随时调用它。在这个例子中,如果玩家的健康值为0,我们将在TakeDamage事件中调用它。所以让我们这样修改我们的TakeDamage:
float APACKT_CPPCharacter::TakeDamage( float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser )
{
// Get the actual damage applied
const float ActualDamage = Super::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);
if (Health <= 0.0)
{
// Player has no health. So return 0.0
return 0.0;
}
// Reduce health by the damage received
Health = Health - ActualDamage;
//Is the health reduced to 0 for the first time?
if (Health <= 0.0)
{
// Clear existing timer
GetWorldTimerManager().ClearTimer(TimerHandle_HealthRegen);
// Call the BLueprint event
PlayerHealthIsZero();
return 0.0;
}
// Set a timer to call Regenerate Health function, if it is not running already
if (!GetWorldTimerManager().IsTimerActive(TimerHandle_HealthRegen))
{
GetWorldTimerManager().SetTimer(TimerHandle_HealthRegen, this, &APACKT_CPPCharacter::RegenerateHealth, InitialDelay);
}
// return the actual damage received
return ActualDamage; }
在前面的代码中,我们在清除恢复计时器后立即调用PlayerHealthIsZero。
现在是编译和运行项目的时候了。在 Visual Studio 中,按F5编译并启动项目。一旦项目加载,打开我们的角色蓝图,你将在详细信息面板中看到我们新的变量被暴露出来:

从这里,你可以打开蓝图图并添加我们的玩家健康值为零事件:

在这个事件中,你可以编写逻辑来播放死亡动画,显示一些 UI 屏幕等等。
摘要
与实际的 C++相比,Unreal C++更容易学习。这是因为 Epic Games 的编程巫师们实现了许多功能,使得编写 Unreal C++变得有趣!你可以通过包括装甲系统、耐力系统等等来扩展你在本章中学到的内容,为你的角色添加功能。通过结合 UMG 和蓝图,你可以显示一个 HUD,显示玩家健康值,也许还有一个当玩家健康值低于 50 时弹出的小型警告系统。在下一章中,你将学习如何打包项目以进行分发。
第十一章. 项目打包
在本书的整个过程中,你学习了 Unreal Engine 4 的基础知识。在本章的最后,我们将回顾所有这些内容,同时了解如何将你的项目打包成一个独立游戏。你还将学习如何快速分发游戏以及如何打包游戏作为发布版本。
回顾
在第一章中,你学习了 Unreal Engine 不同版本之间的区别。正如我提到的,启动器版本是由 Epic 编译的二进制版本,可供你使用。但是,如果你想获取通过启动器尚未提供的最新构建版本,那么你唯一的选择就是从 GitHub 获取源代码。如果你打算使用 Unreal Engine 的源代码版本,我建议从推荐的分支获取源代码。Epic 为他们的艺术家和设计师努力工作,因此大多数时候它每天都会更新,你也可以获得最新的内容!如果你真的想亲自动手或者你有获取最新和最前沿构建的冲动,那么你应该选择 master 分支。请记住,这个分支直接跟踪 Epic 的实时更改,它可能存在错误,甚至可能无法编译。
一旦你启动了引擎,你就可以开始将你的资产导入到内容浏览器中。这是你保存和编辑游戏中使用的资产的地方。内容浏览器提供了许多功能,如基于关键字、标签、资产类型、过滤器等进行搜索,你还可以使用内容浏览器中的集合功能添加对你最常用资产的引用。在搜索时,你可以在名称前添加连字符(-)来排除特定的关键字。例如,如果你想排除所有包含名称floor的资产,那么你可以在内容浏览器中搜索-floor。这将显示所有不包含单词 floor 的资产。
内容浏览器的另一个出色功能是开发者文件夹。这在团队合作中特别有用,当你想在游戏中尝试不同的技术或资产而不影响其他部分时。有一点要记住的是,你应该只将此文件夹严格用于个人或实验性工作,并且你永远不应该在此文件夹之外包含对外部资产的引用。例如,如果你制作了一个想要在添加到游戏之前尝试的资产,那么你可以在开发者文件夹内创建一个测试关卡,并在那里测试一切。将开发者文件夹想象成你自己的私人游乐场,你可以在这里随心所欲地做任何事情,而不会影响他人的工作。开发者文件夹默认不启用。要启用它,点击内容浏览器右下角的视图选项,然后选择显示开发者文件夹:

一旦你启用它,你将在内容浏览器中的内容文件夹下看到一个名为开发者的新文件夹:

开发者文件夹内的文件夹名称自动设置为你的 Windows 用户名。如果你使用源代码控制(例如,Perforce 或 Subversion),那么你可以通过启用其他开发者复选框来查看“其他开发者”文件夹,该复选框位于过滤器 | 其他过滤器下:

了解这些将大大帮助你当你在团队中工作或拥有大量资产时。
就像使用内容浏览器查找导入的资产一样,你使用世界大纲来查找放置在你关卡中的资产。你还可以使用层来组织放置在关卡中的资产。这两个窗口都可以从菜单栏中的窗口召唤:

在第三章“材质”中,你学习了令人惊叹的材质编辑器和我们将使用的常见节点。一位优秀的材质艺术家可以完全改变你游戏的现实感。主要材料和后处理赋予你让游戏看起来逼真或卡通化的能力。我们学习的常见材质表达式不仅用于为资产着色。例如,创建以下材质网络并将其应用于一个简单的网格(例如,一个球体),看看会发生什么:

如果你发现自己多次使用特定的网络,那么创建一个材质函数来整理你的图并使其更有组织会更好。
随着你继续开发你的游戏,你最终将开始调整后处理体积。这让你可以修改游戏的整体外观和感觉。通过在蓝图或 C++中结合后处理,你甚至可以用来影响游戏玩法。一个完美的例子是来自蝙蝠侠阿卡姆系列游戏的侦探视野。你可以使用后处理中的材质来突出世界中的特定对象,甚至用它来渲染其他对象后面的网格的轮廓。
游戏的另一个关键部分是照明,它决定了最终的外观。在这本书中,你学习了不同的光照移动性,它们之间的区别包括常见的光照设置以及它如何影响游戏世界。你还学习了 Epic Games 开发的静态全局照明求解器 Lightmass 全局照明。
如您所知,Lightmass 用于烘焙光照,因此不支持动态光照。当您在游戏中使用 Lightmass 时,您需要确保所有静态网格(未设置为可移动的)都有一个第二 UV 通道,以便产生适当阴影。如果您想使用动态光照(这意味着在运行时可以改变其任何属性的光源——例如,白天和夜晚的循环),Epic 已经包含了光传播体积(LPV)的支持。在撰写本书时,LPV 处于实验阶段,尚未准备好投入生产。这里还有一件额外的事情值得提及,那就是可以改变反射光照的颜色。请看以下材质网络:

使用GIReplace材质节点,您可以改变反射光的颜色。如果您将前面的材质应用到网格上并使用 Lightmass 构建光照,反射光的颜色将变为红色而不是白色。即使我们不需要为反射光使用不同的颜色,我们仍然可以使用此节点在不调整 Lightmass 设置的情况下加深或变亮反射光照。
一旦我们完成了所有基本设置,我们就转向 Blueprints。Blueprint 可视化脚本是一个强大且灵活的基于节点的编辑器,它允许艺术家和设计师快速原型化他们的游戏。主要来说,我们处理两种常见的 Blueprint 类型,它们是级别 Blueprint和类 Blueprint。在这些 Blueprint 内部,我们有事件图、函数图和宏图。在类 Blueprint中,我们添加组件来定义该 Blueprint 是什么以及它们的运行方式。Blueprint 中的节点被应用了各种颜色,以指示它们是哪种类型的节点。一旦您开始使用 Blueprint,您就会熟悉所有节点颜色及其含义。我们看到了如何从一个Actor类创建类 Blueprint以及如何在游戏中动态生成它。我们还看到了如何通过级别 Blueprint与世界中的对象交互。我们在级别中放置了触发器,并在级别 Blueprint中为这些触发器创建了重叠事件,并学习了如何播放 Matinee 序列。
Matinee 是 Unreal Engine 4 中强大的工具之一,主要用于创建电影场景。您已经了解了 Matinee 用户界面以及如何创建一个基本的剪辑场景。由于 Matinee 与其他非线性视频编辑器类似,视频编辑专业人士很容易熟悉 Matinee。尽管 Matinee 用于电影场景,您也可以用它来创建与游戏玩法相关的元素,例如开门、电梯移动等。您甚至可以使用它将现有的电影场景导出为图像序列或 AVI 格式。
在学习完 Matinee 之后,我们继续到下一章学习Unreal 运动图形(UMG)。UMG 是由 Epic 开发的 UI 创作工具。使用 UMG,我们为玩家创建了一个简单的 HUD,并学习了如何与玩家蓝图通信以显示玩家的生命条。我们还为玩家制作了一个浮在角色头顶上的 3D 小部件。
从那里继续,你学习了更多关于级联粒子系统(Cascade Particle System)的知识。你了解了粒子编辑器以及级联编辑器内部可用的各种窗口。在掌握基础知识后,你创建了一个基本的粒子系统,包括使用 GPU Sprites 的碰撞。最后,我们将粒子系统带到了蓝图(Blueprints)中,并学习了如何使用自定义事件和延迟节点随机爆发粒子。
最后,我们深入到了 C++的神奇世界。在那里,你学习了 Visual Studio 2015 的各种版本以及如何下载 Visual Studio 2015 社区版。一旦我们安装了 IDE,我们就基于第三人称模板创建了一个新的 C++项目。从那里,我们扩展了它以包括我们角色类的生命值和生命值恢复。你还学习了如何将变量和函数暴露给蓝图以及如何在蓝图中访问它们。
打包项目
现在你已经学习了大多数 Unreal Engine 4 的基础知识,让我们看看如何打包你的游戏。在我们打包游戏之前,我们需要确保我们为游戏设置了一个默认地图,该地图将在你的打包游戏启动时加载。你可以从项目设置窗口设置游戏默认地图选项。例如,你可以将游戏默认地图选项设置为你的主菜单地图:

要为游戏设置默认地图,请按照以下步骤操作:
-
点击编辑菜单。
-
点击项目设置。
-
选择地图与模式。
-
在游戏默认地图中选择你的新地图。
快速打包
一旦你设置了游戏默认地图选项,你需要选择构建配置:

在打包项目时,有三种类型的构建配置可用:
-
DebugGame:这种配置将包含所有调试信息。出于测试目的,你可以使用这个配置。 -
开发:这种配置与DebugGame配置构建相比,由于调试支持最小化,因此提供了更好的性能。 -
发布:当你想要分发游戏时,应该选择这个设置。
一旦你选择了构建配置,你就可以从文件 | 打包项目进行游戏打包,然后选择你的平台。例如,这里是为Windows 64 位打包游戏的选项:

一旦选择该选项,编辑器可能会提示您选择一个目标目录以保存打包的游戏。一旦设置路径,编辑器将开始为所选平台构建和准备内容。如果打包成功,您将在之前设置的目录下看到打包的游戏。
打包发布版本
之前提到的方 法是用于快速打包和向最终用户分发游戏。然而,前面的方法不能构建您的游戏的 DLC 或补丁,因此在本节中,您将学习如何为您的游戏创建发布版本。
首先,让我们打开 项目启动器 窗口。项目启动器 提供了打包游戏的先进工作流程:

要创建自定义启动配置文件,请点击前面截图所示的增加(+)按钮。一旦点击,您将看到一个带有以下新设置的新窗口:

在前面的窗口中,执行以下操作:
-
启用 构建 复选框。
-
将 构建配置 选项设置为 发布。
-
将下拉菜单设置为 按书。
-
在本例中,我们选择了 WindowsNoEditor 以在 Windows 上进行测试。
-
选择文化。这用于本地化。默认情况下,en-US 被选中。
完成所有这些设置后,展开 发布/DLC/修补设置 和 高级设置 部分:

在这些部分中执行以下操作:
-
启用 创建用于分发的游戏发布版本。
-
将新发布版本的名称设置为 1.0。
-
启用 将所有内容存储在单个文件中(UnrealPak)。
-
将 烹饪构建 配置 部分设置为 发布。
-
将
–stage命令行作为 附加烹饪选项 添加。请注意,在输入后不要按回车键。只需点击其他任何地方即可应用该命令。
设置完成后,将 打包 和 部署 的最后两个选项分别设置为 不打包 和 不部署:

完成所有这些操作后,点击 项目启动器 窗口右上角的 后退 按钮,您将看到准备好的新配置文件,可以开始构建:

简单地点击 启动 按钮,项目启动器 将构建、准备和打包您的游戏。这可能会根据您游戏复杂度的大小而花费一些时间:

如果打包成功,您可以在 项目启动器 窗口中看到:

您可以在项目文件夹下的 Saved | StagedBuilds | WindowsNoEditor 文件夹中找到您的打包游戏。现在您可以向其他用户分发这个打包游戏。
摘要
在这本书中,您学习了虚幻引擎 4 的基础知识。我们与您一起开始这段旅程,学习了如何下载引擎以及如何导入您的资产。从那里,您学习了材质编辑器和它的常见方面。然后您学习了后期处理,如何使用灯光以及灯光在视频游戏中的重要性。您还学习了蓝图,这是虚幻引擎 4 的视觉脚本语言。我们从蓝图继续到 UMG,您可以使用它来创建游戏中任何类型的菜单。由于游戏如果没有视觉效果和场景将毫无意义,您学习了 Cascade 粒子编辑器和 Matinee。从那里,我们深入到 C++的世界,学习这种强大语言的基础。最后,您学习了如何打包游戏并将其分发给他人。
参考文献
您学习虚幻引擎 4 的旅程并不止于此。您可以通过访问以下链接来进一步扩展您的知识:
-
虚幻引擎 社区
-
虚幻引擎 官方 Twitch 直播
-
虚幻引擎 YouTube 频道
-
虚幻引擎 AnswerHub
-
虚幻引擎 官方文档


























































浙公网安备 33010602011771号