zoukankan      html  css  js  c++  java
  • Unreal Engine 4 系列教程 Part 2:蓝图教程

    原文:Unreal Engine 4 Blueprints Tutorial
    作者:Tommy Tran
    译者:Shuchang Liu

    在本篇教程里,你将学会如何用蓝图系统创建玩家角色,设置输入,并编写角色通过触碰,收集道具的游戏逻辑。

    蓝图是Unreal Engine 4的一套可视化脚本系统,通过蓝图可以快速制作游戏原型。你不再需要一行行的编写代码,取而代之的是可视化操作:拖拽节点,在UI里设置节点参数,给节点进行连线。

    除了作为一款非常便捷的原型工具,蓝图也降低了非开发人员制作游戏逻辑的门槛。

    在本篇教程,你将使用蓝图来:

    • 设置垂直视角摄像机
    • 创建具备基本移动的玩家控制器角色
    • 设置玩家输入
    • 创建可被角色触碰并收集的道具

    注意:本篇教程假定你已了解Unreal Engine 4的基本操作界面。你也应该熟悉基本的蓝图概念,比如组件和节点。如果你需要复习以上内容,点击入门教程

    注意:本篇教程只是Unreal Engine 4系列教程的其中一篇:

    起步入门

    下载示例项目并解压。进入项目文件夹,双击BananaCollector.uproject打开项目。

    注意:如果你看到了项目是由较早的引擎版本创建的提示,这很正常(因为引擎经常更新版本)。你可以选择以拷贝副本的形式打开,也可以直接转换项目版本打开。

    你可以看到以下的场景。我们创建的角色会在场景内移动并收集道具。

    为了方便起见,我已经给项目文件做了文件夹分类,如下图所示:

    你可以点击红框处按钮来显示/隐藏侧边栏列表。

    创建玩家

    点击进入Content Browser界面的Blueprints文件夹。点击Add New按钮并选择Blueprint Class

    由于玩家需要能够获取输入,Pawn类比较适合。在弹出窗口选择创建Pawn,将其命名为BP_Player

    注意:选择Character类创建也可以,它还默认引入了移动组件。不过,既然我们想要自己动手实现移动,Pawn类已经足够了。

    关联摄像机

    摄像机是玩家观察游戏世界的方式。我们要创建一个垂直视角观察玩家角色的摄像机。

    在Content Browser 双击BP_Player打开蓝图编辑器。

    为了创建摄像机,在Components面板点击Add Component并选择Camera

    为了让摄像机视角自顶向下,我们需要先把它放在玩家角色上方。选中摄像机组件,再切换到Viewport页签。

    按下W键激活移动操作杆,将摄像机移动到(-1100, 0, 2000)。或者,你可以在Location字段输入坐标点来移动摄像机。

    如果摄像机被移出界面外,按下F键就可以重新定位看到摄像机。

    接着,按下E键激活旋转操作杆,将摄像机沿Y轴旋转-60度。

    玩家表示

    我们用一个红色方块来表示玩家,所以需要使用Static Mesh组件进行展示。

    首先,在Components面板左键点击空白处取消选中Camera组件。否则,新加的组件会成为摄像机的子节点。

    点击Add Component并选择Static Mesh

    为了展示红色方块,选择Static Mesh组件,随后在Details页签Static Mesh属性点击下拉框,选择SM_Cube

    你在关卡场景里应该就能看到如下画面(如果看不到,你可以在Viewport窗口按下F键聚焦画面)

    现在,是时候在关卡里动态生成玩家了。点击Compile按钮并回到主编辑器。

    生成玩家

    为了让玩家能够控制角色,你需要明确两件事:

    1. 玩家所要控制的Pawn类
    2. 角色应该在哪里生成

    你可以通过创建Game Mode类(游戏模式类)来实现第一点。

    创建游戏模式

    游戏模式是一个类,用于控制玩家进入游戏的方式。比如,在多人游戏里,可以使用游戏模式,决定每个玩家在哪里生成。更重要的是,游戏模式决定了玩家使用哪个角色。

    在Content Browser里点击进入Blueprints文件夹。点击Add New按钮并选择Blueprint Class

    从弹出窗口里选择Game Mode Base,并命名为GM_Tutorial

    现在,你需要指定哪个Pawn作为默认类。双击GM_Tutorial打开蓝图编辑器。

    留意Details面板的Classes部分。点击Default Pawn Class属性的下拉框,并选择BP_Player

    其次,关卡还需要知道当前使用哪个游戏模式。你可以在World Settings里指明这一点。点击Compile并关闭蓝图编辑器。

    每个关卡都有自己的设置。你可以通过WindowWorld Settings查看设置。同样地,也可以在Toolbar选择SettingsWorld Settings进行查看。

    Details页签旁边就会出现World Settings页签。点击该页签的GameMode Override字段,选择GM_Tutorial

    现在可以看到Game Mode类已经修改成GM_Tutorial

    最后,我们还需要指定玩家的生成位置。通过在关卡里放置Player Start(玩家出生点)即可。

    放置玩家出生点

    在生成玩家的过程中,游戏模式会寻找关卡中是否有玩家出生点。如果有,游戏模式就会在该点生成玩家。

    为了放置玩家出生点,在Modes面板搜索Player Start左键拖拽 Player Start至Viewport面板。

    你可以随意放置玩家出生点。放好后,点击Toolbar的Play按钮。玩家就会在出生点生成。

    如果想要退出游戏,点击Toolbar的Stop按钮或按下Esc键皆可。如果你看不到鼠标指针,按下Shift+F1

    如果玩家不能控制移动,那其实算不上游戏,对吧?我们的下个任务就是设置输入控制。

    设置输入

    将某个按键指定成触发某个行为,称之为按键绑定。

    在Unreal里,你可以通过按键触发event(事件)的方式来实现按键绑定。事件节点是一类当接收到特定行为时,触发执行的节点(比如在这个例子里,当你按下绑定按键时,触发执行某个事件节点)。当某个事件被触发时,任何跟事件节点连接的节点就会被执行。

    这种按键绑定的方式非常有好处,因为这意味着你不需要硬编码按键对应的逻辑。

    比如,你绑定了鼠标左键并命名为Shoot事件。任何有射击能力的Actor都可以使用Shoot事件,用于检测玩家何时按下了鼠标左键。如果你想修改射击对应绑定的按键,只要在输入设置里修改即可。

    如果以硬编码方式实现,你需要遍历每个Actor,分别修改射击对应绑定的按键。

    轴映射和操作映射

    EditProject Settings里可以看到输入设置。点击Engine部分的Input选项进入设置界面。

    Bindings就是用于设置输入的部分。

    Unreal提供了两类按键绑定方法:

    • Action Mapping(操作映射):这类绑定只有两种状态:按下或者没按下。行为只会在按下或释放按键的时候触发。这类绑定适用于没有中间状态的行为,比如枪械射击。
    • Axis Mapping(轴映射):这类绑定输出一个称之为Axis Value(下文有更多介绍)的数字。每帧都会触发对应的轴事件。这类绑定通常用于摇杆或者鼠标。

    在这篇教程里,我们会使用Axis Mapping

    创建移动映射

    首先,你需要创建两组Axis Mapping。这样就可以实现多按键触发同一个事件。

    为了创建一组新的Axis Mapping,点击Axis Mappings右侧的+号。创建两组Axis Mapping,分别命名为MoveForwardMoveRight

    MoveForward负责前后移动。MoveRight负责左右移动。

    我们需要把移动映射到四个按键上:WASD。现在只有两个插槽用于映射按键。通过点击每组映射文本框右侧的+号,添加映射插槽。

    接着点击每组插槽的下拉框,将WS键映射到MoveForwardAD键映射到MoveRight

    接着,我们需要设置Scale字段。

    Axis Value和Input Scale

    在你设置Scale字段前,我们需要了解它是怎么跟axis values搭配起作用的。

    Axis Value的输出数值取决于输入类型和使用方式。按钮点击会输出1。摇杆根据推动方向和力度,输出-1~1之间的数值。

    你可以使用Axis Value控制角色的移动速度。比如,如果你把摇杆推到了最边上,Axis Value是1。如果你只推一半,Axis Value就是0.5。

    将Axis Value跟某个速度变量进行相乘,你就能够调整摇杆的速度。

    你也可以通过Axis Value判断出方向。如果你将角色速度与一个Axis Value正数相乘,得到的就是正数偏移。角色速度与一个Axis Value负数相乘,得到的就是负数偏移。将偏移值与角色位置相加,就能知道角色往哪个方向移动了。

    由于键盘按键只能输出0或1的Axis Value,你可以使用Scale来将其转换成负数。通过Axis Value和Scale值相乘就可以做到这点。

    如果正数(Axis Value)和负数(Scale)相乘,按键输出就是负数。

    因此我们点击修改按键SAScale字段文本为-1。

    接着,有趣的部分来了:让角色动起来!关闭项目设置面板,双击BP_Player打开蓝图编辑器。

    角色移动

    首先,你需要获取移动映射的事件。在事件图表空白处点击右键打开节点列表。从弹出菜单中搜索MoveForward。添加处于Axis Events下的MoveForward节点。注意我们要添加的是Axis Events下的红色节点,而非Axis Values下的绿色节点。

    添加MoveRight节点的步骤同上。

    现在,我们需要设置下MoveForward节点。

    使用变量

    为了实现移动,我们需要指定角色的运动速度。最简单的方法是通过变量保存移动速度。

    要新建变量,我们点击My Blueprint页签Variable部分的+号。

    选中新建的变量,观察Details页签。将变量名重命名为MaxSpeed。随后,点击Variable Type的下拉框选择Float,将变量类型修改为Float

    接着,需要给变量设置默认值。在这之前,先点击Toolbar上的Compile按钮。

    保持变量选中,在Details页签的Default Value区域,将MaxSpeed的默认值设为10

    接着,将MaxSpeed变量从My Blueprint页签拖拽至Event Graph。并选择弹出菜单的Get

    我们现在需要将MaxSpeedAxis Value相乘来得出最终移动速度和方向。添加float * float节点,并连接Axis ValueMaxSpeed

    获取角色朝向

    为了向前移动,首先需要知道角色的朝向。幸运地是,Unreal里有这样的节点。我们需要添加Get Actor Forward Vector节点。

    接着,添加Add Movement Input节点。该节点通过获取方向和数值,将其转换成移动偏移值。我们按下图连接各个节点:

    白线代表节点执行顺序。换言之,玩家进行操作,触发相应事件并执行InputAxis MoveForward节点,随后执行Add Movement Input节点。

    Add Movement Input节点需要如下输入:

    • Target:默认为self,在这里就是玩家角色自己(红色方块)。
    • World Direction:目标移动方向,在这里就是玩家角色的朝向。
    • Scale Value:玩家移动距离,在这里为Max Speed * Axis Value(值范围为-1~1)。

    MoveRight事件的设置步骤同上,除了要把Get Actor Forward Vector节点替换为Get Actor Right Vector节点。试着不对照前面的操作指引,自己动手看看!

    添加移动偏移

    为了让角色真正动起来,我们还需要将Add Movement Input节点计算得出的偏移值,累加到角色当前位置上。

    基本上我们的策略就是让游戏角色每帧移动一点点,所以我们需要在Event Tick事件添加运动节点,每帧进行调用。

    现在看看Event Graph有没有Event Tick节点,它应该处于灰化状态,如果没有就创建对应节点。

    为了获取偏移值,创建Consume Movement Input Vector节点。要累加偏移值到玩家角色上,还需要添加AddActorLocalOffset节点。随后如下图连接节点:

    这样意味着在游戏每帧,你会获取角色的移动输入,并将其累加在角色当前位置上。

    点击Compile,回到主编辑器并点击Play。你就能操控红色方块四处移动了!

    这里有个小问题。高配机器有可能运行帧率更高。由于Event Tick事件每帧调用,那同等时间内运动节点执行的次数更多。导致的结果就是高配机器角色移动得更快,反之亦然。

    为了避免这个问题,角色运动必须是帧率无关的。

    注意:我已经做了按键绑定用于展示帧率有关会产生的影响。按下数字键0将帧率调成60,按下数字键1将重置帧率。控制角色四处移动,看看不同帧率对移动速度的影响。

    帧率无关

    帧率无关意味着不管帧率是多少,相同时间的游戏运行,会产生完全一致的结果。幸运地是,在Unreal里要做到这点非常容易。

    退出游戏,并打开BP_Player。接着,观察Event Tick节点的Delta Seconds字段。

    Delta Seconds为当前帧的Event Tick调用与上一帧Event Tick调用的时间间隔。通过将偏移值与Delta Seconds相乘,角色运动就是帧率无关的。

    比如,你的角色最高速度是100。如果距离上一帧Event Tick已经过了1秒,则角色移动100个单元。如果只过了0.5秒,则角色运动50个单元。

    如果角色运动是帧率相关的,那就会产生不过帧率高低,每帧固定移动100单元的结果。

    为了将偏移值与Delta Seconds相乘,添加vector * float节点。之后,如下图进行连线:

    由于每帧间隔时间很短,角色移动起来会很慢,所以可以将MaxSpeed的默认值调大至600

    至此恭喜你,成功解锁了帧率无关成就!

    你可能注意到了,方块现在会穿透其他物体。为了解决这个问题,我们需要用上碰撞检测

    角色碰撞

    为了能够互相碰撞,角色需要一个代表其碰撞区域(通常称之为碰撞体)的东西。你可以使用以下任一种:

    • Collision mesh(碰撞网格):这个通常在网格导入时就会生成(如果你勾选了允许)。用户也可以用3D软件创建自定义碰撞网格。红色方块导入时就自动生成了碰撞网格。
    • Collision component(碰撞组件):一般由三种形状:盒子,胶囊体和球体。你可以通过Components面板进行添加。通常用于简单碰撞。

    下面就是一个人物和其碰撞体的例子。

    当一个碰撞体碰到了另个碰撞体,碰撞就产生了。

    设置碰撞

    你可能会奇怪,方块有碰撞体,却没有检测到碰撞。当你移动方块时,Unreal只认为方块的根组件可产生碰撞。由于方块的根组件并没有任何碰撞体,所以就穿透了其他物体。

    注意:一个root组件没有碰撞体的角色,同样可以挡住其他角色。但如果你移动这个角色,它是不会与任何物体产生碰撞的。

    所以,为了使用碰撞网格,StaticMesh必须作为根组件存在。我们通过在Components面板左键拖拽StaticMesh至DefaultSceneRoot。释放鼠标,StaticMesh现在就成了根组件了。

    最后还要做一件事情。切换到Event Graph页签,将AddActorLocalOffset节点的Sweep输入勾选为true

    简单来讲,AddActorLocalOffset会将角色从旧位置瞬移到新位置上。Sweep可以确保旧位置和新位置之间的物体都能与角色进行碰撞检测。

    回到主编辑器并点击Play。现在方块能与关卡场景产生碰撞了!

    创建道具

    任何东西都能成为供玩家触碰拾取的道具。这里我们使用BP_Banana作为道具。

    为了检测方块是否碰到了道具,我们需要一个在产生碰撞时,触发执行的事件节点。我们可以使用碰撞响应来生成事件。

    碰撞响应也决定了角色之间的碰撞后行为。有以下三类碰撞响应:IgnoreOverlapBlock。以下是它们互相之间的作用结果:

    虽然可以使用Overlap或Block的任一种,本篇教程只展示如何使用Overlap。

    设置碰撞响应

    退出游戏并打开BP_Banana。选择StaticMesh组件并观察Details面板,Collision部分可以设置碰撞响应。

    如图所示,大部分设置都是灰置的。为了编辑它们,左键点击Collision Presets的下拉框,选择Custom选项。

    现在,你需要指定道具和方块之间的碰撞响应。

    组件有一项属性称之为对象类型。对象类型是一种给角色进行简单分类的方法。你可以在这里了解更多关于对象类型的内容。

    由于方块的类型是WorldDynamic,我们需要修改该类型对象的碰撞响应。在Collision Responses设置下,左键点击WorldDynamic中间的勾选框,将碰撞响应改成Overlap

    碰撞处理

    为了获取碰撞情况并进行处理,我们需要用到overlap事件。在Components面板右键点击StaticMesh。从弹出菜单中,选择Add EventAdd OnComponentBeginOverlap

    Event Graph界面就会出现OnComponentBeginOverlap (StaticMesh)节点。

    最后,添加DestroyActor节点,并连接OnComponentBeginOverlap (StaticMesh)节点。顾名思义,该节点会将目标角色从游戏中移除。由于我们没有显式指定Target,所以它会销毁调用该节点的角色。

    放置道具

    关闭蓝图编辑器,并确保Content Browser打开了Blueprints文件夹。

    通过左键拖拽 BP_Banana至Viewport界面来在关卡放置香蕉道具。

    点击Play按钮,开始收集香蕉吧!

    后续学习

    你可以在这里下载完整项目

    你现在距离成为Unreal Engine专家又近了一步了。希望这篇教程没有难倒你。

    如果你还想继续学习Unreal Engine 4引擎,点击下篇教程,我会进一步讲解Unreal Engine 4引擎的材质系统。

  • 相关阅读:
    【leetcode】416. Partition Equal Subset Sum
    【leetcode】893. Groups of Special-Equivalent Strings
    【leetcode】892. Surface Area of 3D Shapes
    【leetcode】883. Projection Area of 3D Shapes
    【leetcode】140. Word Break II
    【leetcode】126. Word Ladder II
    【leetcode】44. Wildcard Matching
    【leetcode】336. Palindrome Pairs
    【leetcode】354. Russian Doll Envelopes
    2017.12.22 英语面试手记
  • 原文地址:https://www.cnblogs.com/leoin2012/p/11713413.html
Copyright © 2011-2022 走看看