原文:How to Create a Simple Game in Unreal Engine 4
做者:Tommy Tran
译者:Shuchang Liuhtml
在本篇教程中,你将学习制做一个第一人称动做游戏,学习如何随机生成并躲避障碍物。web
若是你刚开始接触游戏,一个经常会收到的建议就是学习制做一款简单游戏,由于你能学会制做简单的游戏玩法,物件交互。app
本篇教程中,咱们将制做一个第一人称动做游戏,涉及如下知识点:dom
最后,咱们将制做出以下图同样的小游戏:编辑器
请注意,教程涉及蓝图和UMG部份内容。若是你须要复习有关内容,请查看蓝图教程和UI教程。ide
注意:本篇教程只是Unreal Engine 4系列教程的其中一篇:svg
下载示例项目并解压。进入项目文件夹,双击InfiniteMatrix.uproject打开项目。函数
注意:若是你看到了项目是由较早的引擎版本建立的提示,这很正常(由于引擎常常更新版本)。你能够选择以拷贝副本的形式打开,也能够直接转换项目版本打开。oop
按下Play运行游戏尝试控制移动。你能够经过移动鼠标进行垂直,水平移动。学习
首先要作的是让玩家角色持续向前动起来。
Content Browser打开Blueprints文件夹并双击打开BP_Player。
为了让玩家角色向前运动起来,咱们须要给玩家位置每帧累加偏移值。
首先,建立变量定义玩家前移的速度。建立名为ForwardSpeed的Float变量,将默认值调成2000。
接着,在Event Graph找到Event Tick节点,建立以下设置:
经过ForwardSpeed与Delta Seconds相乘,就能得到帧率无关的运动位移。
注意:若是你不熟悉帧率无关的概念,请阅读蓝图教程。
接着,咱们须要将数值结果应用到角色上,让其沿指定轴运动。
为了让角色移动,建立AddActorWorldOffset节点。将Sweep选中框勾选为true。
若是咱们直接将Float节点与Delta Location输入引脚相连,Unreal会将其自动转换为Vector。
然而,这样会致使Vector的x,y,z轴份量都设置成Float节点值。在教程例子中,玩家角色应该只沿着X轴移动。幸运地是,咱们能够将Vector变量分解成三个Float组件。
确保AddActorWorldOffset节点的Delta Location引脚没有任何链接。右键点击Delta Location引脚,从弹出菜单中选择Split Struct Pin。
最后,以下图进行链接:
让咱们回顾下:
点击Compile并回到主编辑器。角色就会沿着隧道穿行了。
与其手动放置一段段的隧道,咱们接下来会建立蓝图用于自动生成隧道。
Content Browser跳转到Blueprints文件夹,建立以Actor为父类的Blueprint Class,命名为BP_TunnelSpawner并双击打开。
因为游戏过程会持续不断的生成隧道,咱们能够建立一个相应的函数。在My Blueprint面板建立名为SpawnTunnel的新函数。该函数负责在指定位置建立隧道。
为了传递位置数据,这个函数须要一个输入参数。它在函数节点以输入引脚的方式存在。
在函数内部的入口节点,它又以输出引脚方式存在。
如今让咱们来建立一个输入参数。确保界面处于SpawnTunnel函数的图标。选择入口节点,而后点击Details面板Inputs部分的+号。
将输入参数重命名为SpawnLocation,并将参数类型改成Vector。
为了生成隧道,须要添加Spawn Actor From Class节点。点击Class引脚的下拉框,选择BP_Tunnel。
为了设置生成位置,右键点击Spawn Transform引脚,从弹出菜单选择Split Struct Pin。随后如图链接Spawn Actor From Class节点与Entry节点:
下面来测试下吧!
切换到Event Graph并找到Event BeginPlay节点。添加SpawnTunnel节点并与Event BeginPlay节点相连。
将SpawnTunnel节点的Spawn Location设置为(2000, 0, 500)。
如今当游戏启动时,隧道会生成在距离玩家角色比较远的地方。点击Compile并回到主编辑器。
首先,删除关卡场景里的BP_Tunnel。在World Outliner里左键点击BP_Tunnel,而后按Delete键删除隧道。
接着,在Content Browser里左键拖拽BP_TunnelSpawner至Viewport,这样就往关卡中添加了对应实例。
如今点击Play运行游戏,可以看到玩家角色上方会生成一个隧道。
测试完毕后,再次打开BP_TunnelSpawner。将SpawnTunnel节点的Spawn Location重置为(0, 0, 0)。
随后,点击Compile并返回主编辑器。
教程下一部分,咱们将编写BP_Tunnel蓝图。
BP_Tunnel蓝图须要干两件事。首先它须要检测什么时候须要生成一段新隧道。为了实现这点,咱们须要建立一个触发区域。一旦触发,BP_Tunnel负责通知BP_TunnelSpawner生成一段新隧道。这样就能实现隧道绵延无尽的错觉。
其次它须要肯定下一段隧道的生成点。BP_TunnelSpawner会根据这个点来生成隧道。
如今先看看怎么建立触发区域吧。
打开BP_Tunnel并来到Components面板,添加Box Collision组件,将其命名为TriggerZone。
此时组件的碰撞区域还很小。留意Details面板的Shape部分设置,将Box Extent属性改成(32, 500, 500)。
接着,Location属性设为(2532, 0, 0),将触发区域位置摆放到隧道网格末端。这意味着玩家角色触达隧道末端时就应该生成一段新隧道了。
如今,是时候建立生成点了。
为了标记生成点位置,咱们可使用Scene组件。Scene组件很是适合用于标记位置,由于该组件没有外观显示,只有一个Transform。同时该组件在Viewport又是可视的,方便咱们知道生成点在哪。
没有选中任何东西的前提下,在Components面板添加Scene组件,并命名为SpawnPoint。
隧道网格沿X轴总共2500单位长,因此生成点应该就在这,在Details面板设置Location参数为(2500, 0, 0)。
接下来须要建立一个函数,负责在生成点生成隧道。
点击Compile并切换到BP_TunnelSpawner。
新的BP_Tunnel永远应该在最远隧道的生成点生成。这样看起来,隧道就是无穷尽的。
因为最远隧道一定是最新生成的隧道,因此咱们不难得到其引用。
打开SpawnTunnel图表,在Spawn Actor From Class节点的Return Value引脚右键点击,从弹出菜单中选择Promote to Variable并命名为NewestTunnel。
如今,咱们就得到了最远隧道的引用了。
接着,建立新函数并命名为SpawnTunnelAtSpawnPoint。建立以下图表:
这样设置就能够得到SpawnPoint组件的位置,并在该点生成一段新隧道。
为了让BP_Tunnel能通知调用到BP_TunnelSpawner,前者须要有后者的引用。不然,BP_TunnelSpawner就不知道什么时候生成隧道了。
点击Compile并关闭SpawnTunnelAtSpawnPoint图表,随后打开BP_Tunnel。
添加新变量,命名为TunnelSpawner,将Variable Type类型设置为BP_TunnelSpawner\Object Reference。
点击Compile并切换回BP_TunnelSpawner。
打开SpawnTunnel图表添加对应节点:
如今,每一个隧道都能得到BP_TunnelSpawner的引用。
接着,咱们要让BP_TunnelSpawner能在玩家角色进入触发区域时生成新隧道。
点击Compile并切回到BP_Tunnel。
在Components面板右键点击,在弹出菜单中选择Add Event\Add OnComponentBeginOverlap。Event Graph会新增下面节点:
这个节点会在Actor触碰触发区域时执行。
首先,咱们要确认触碰触发区域的Actor是玩家角色。
左键拖拽Other Actor引脚至空白处,从弹出菜单中选择Cast to BP_Player节点。
注意:因为新隧道会在另外一段隧道的末端生成,它会触发执行隧道的TriggerZone节点,Cast to BP_Player节点能拦截其余Actor执行后续逻辑。
接着,在Cast to BP_Player节点后面添加以下节点:
让咱们再回顾以上步骤:
点击Compile,回到主编辑器并点击Play。一旦触达隧道末端,就会又有一段隧道生成。
至此,虽然游戏一直在生成隧道,看起来并不像穿行在无尽的隧道。咱们能够经过在屏幕上多显示几条隧道来优化画面表现。后面再配合上障碍点的显示,玩家就不会留意到隧道的忽然生成了。
首先,咱们要建立函数用于生成必定数量的隧道。
打开BP_TunnelSpawner建立名为SpawnInitialTunnels的新函数。
为了生成必定数量的隧道,咱们可使用ForLoop节点。该节点会执行屡次链接的节点。添加ForLoop节点并与入口节点相连。
为了使得ForLoop节点执行n次,咱们须要将Last Index设置成n-1。
在这篇教程里,咱们须要生成3段隧道,为了循环执行3次,将Last Index设置成2。
注意:若是不显式设置First Index或Last Index字段,默认为0。
玩家应该在游戏开始时就处于隧道中,因此咱们能够将第一段隧道生成在玩家位置。
为了判断第一段隧道是否已生成,咱们能够检查NewestTunnel字段是否有值。若是没有值则说明第一段隧道还未生成,由于NewestTunnel字段是在游戏生成第一段隧道后设值的。
为了进行检查,在ForLoop节点后添加IsValid节点(带有问号图标)。
接着,获取NewestTunnel引用链接IsValid节点的Input Object引脚。
若是NewestTunnel没有值,执行Is Not Valid引脚,反之执行另外一个引脚。
在IsValid节点的Is Not Valid引脚分支添加以下节点:
这样就能在玩家位置生成一段隧道。
好了,接下来让咱们来生成其余隧道。
添加SpawnTunnelAtSpawnPoint节点并与IsValid节点的Is Valid引脚链接。
下图就是最终图表:
小结:
接着,在Event Graph中删除SpawnTunnel节点,并在Event BeginPlay节点后添加SpawnInitialTunnels节点。
如今再运行游戏,就会生成了3段隧道。
点击Compile,回到主编辑器点击Play。隧道看起来长多了!
这个游戏目前为止尚未游戏难度,让咱们来加上一些障碍点。
这些是咱们建立障碍点会用上网格:
在Components面板双击打开BP_Tunnel。添加Static Mesh组件,命名为WallMesh。
在Details面板将它的Static Mesh属性改成SM_Hole_01。
再将Location属性改成(2470, 0, 0)。这样网格就会处于隧道末端位置。
为了让游戏更有趣些,最好让这面障碍墙转动起来。添加Float变量,命名为RotateSpeed,设置默认值为30。
切换到Event Graph找到Event Tick。进行以下设置:
这样WallMesh每帧都会转动一点点。
点击Compile并返回主编辑器。按下Play看看转动的障碍墙吧。
接着让咱们再来添加一些随机性吧。
在此咱们不须要给每种不一样样式的障碍都建立一个蓝图,咱们只要随机选择WallMesh便可。
打开BP_Tunnel并建立新函数RandomizeWall。随后,以下图设置图表:
顾名思义,Set Static Mesh节点会将WallMesh设置为指定的网格。
想要建立一个网格列表,咱们可使用Select节点。
左键拖拽New Mesh引脚至空白处,从弹出菜单中选择Select节点。
Select节点容许你设置一个选项列表。Index节点决定Select节点输出哪一个列表选项。
既然有4个可用墙面网格,咱们须要再建立2个Option引脚。经过右键点击Select节点,从弹出菜单中选择Add Option Pin。
接着,以下设置每一个选项:
如今,再随机选中一个选项。
咱们可使用Random Integer in Range节点来获取一个随机数字,该节点会返回>=Min且<=Max的数值。
添加Random Integer in Range节点并与Select节点的Index引脚相连。
将Max值设为3。这样就会随机返回如下4个数字中的一个:0,1,2,3。
为了增长一些随机性,咱们再给WallMesh添加一个随机旋转值。在Set Static Mesh节点后添加以下图表:
这样WallMesh就会有一个0~360度的旋转偏移值。
下图是最终的图表:
小结:
点击Compile并关闭RandomizeWall图表。
切换到BP_TunnelSpawner并打开SpawnTunnel图表。添加下图的高亮节点:
如今,只要建立隧道,都会跟着随机生成障碍墙网格。
关闭SpawnTunnel图表并点击Compile。返回主编辑器并按下Play体验不一样的障碍墙!
若是你撞上了墙,应该会立刻停下来。若是你控制移动并穿过了墙上的洞,就能够继续前行。
咱们下一步要作的是让玩家角色在撞上墙后中止移动。
要控制玩家角色能不能前行,咱们可使用Boolean变量。该变量只有两种状态:true和false。
打开BP_Player并建立新Boolean变量,命名为IsDead。
接着,找到Event Tick节点并建立Branch节点。
随后,获取IsDead引用并链接Branch节点的Condition引脚。
链接Event Tick节点与Branch节点。随后,链接Branch节点的False引脚与AddActorWorldOffset节点。
如今,只要IsDead设置为true,玩家角色就会中止移动。
接着,咱们要在玩家撞到墙时设置IsDead变量。
点击Compile并切换到BP_Tunnel。在Components面板右键点击WallMesh,在弹出菜单中选择Add Event\Add OnComponentHit。Event Graph就会新增以下节点:
只要Actor跟WallMesh触碰,节点就会执行。
首先,咱们须要检查碰撞Actor是否为玩家。
左键拖拽Other Actor引脚至空白处,从弹出菜单中选择Cast to BP_Player。
接着,左键拖拽Cast to BP_Player节点的BP_Player引脚至空白处,从弹出菜单中选择Set Is Dead节点。
将IsDead的勾选框勾选为true。
点击Compile并回到主编辑器。点击Play尝试在游戏撞上墙。你会发现你还能够上下移动,但已经再也不继续前行了。
下一部分教程,咱们将要在玩家撞上墙时显示重玩按钮。
咱们要显示的控件叫WBP_Restart。你能够在UI文件夹找到它。控件看起来是这个样子的:
为了控制控件的显隐,首先要得到它的引用。打开BP_Player并建立变量RestartWidget,将Variable Type改成WBP_Restart\Object Reference。
接着,在Event Graph找到Event BeginPlay节点。
新增Create Widget节点并设置Class为WBP_Restart。
随后,添加Set Restart Widget节点并以下图链接:
如今,当玩家生成时,会同时生成WBP_Restart实例。下一步是建立函数来显示它。
建立名为DisplayRestart的新函数,而后以下图设置其图表:
小结:
要显示重玩按钮,咱们所要作的事就是在玩家撞墙后,调用DisplayRestart函数。
关闭DisplayRestart图表并点击Compile。
切换到BP_Tunnel并找到On Component Hit (WallMesh)节点。
在节点链的末端添加DisplayRestart节点。
点击Compile并关闭BP_Tunnel。回到主编辑器并点击Play。若是你撞上了墙,就会显示重玩按钮。
如今还剩最后一步工做,在玩家点击按钮后重置游戏。
重置游戏须要作两件事:
首先咱们先来重置玩家。
打开BP_Player并建立新函数RestartGame,建立以下图表:
小结:
而后,咱们还须要从新生成隧道。
点击Compile并关闭BP_Player。
打开BP_TunnelSpawner并跳转到SpawnInitialTunnels图表。
首先,在生成新隧道前,要先把此前生成的隧道所有移除掉。
在入口节点后面添加Sequence节点。将Then 1引脚与ForLoop节点相连。
注意:Sequence节点用于序列执行它的输出引脚。善用Sequence节点有利于图表的组织,特别是一味滥用节点链的状况下,图表会变得很是长。
接着,建立以下节点:
这样就能把此前生成的隧道所有移除掉。
最后,将Sequence节点的Then 0引脚与Get All Actors of Class节点相连。这样就能确保在生成新隧道前,移除已有隧道。
看看最终的图表:
还剩最后一件事了,处理按钮点击。
点击Compile并关闭BP_TunnelSpawner。
打开Content Browser的UI文件夹,双击打开WBP_Restart。
选中RestartButton并打开Details面板,点击Events下的OnClicked右侧按钮。
Unreal会建立On Clicked (RestartButton)节点。这个节点会在玩家点击RestartButton时触发执行。
以下图设置函数图表:
小结:
注意:你可能奇怪咱们要用Get All Actors Of Class节点,而不是直接获取BP_TunnelSpawner引用。主要缘由是BP_Tunnel与WBP_Restart并无任何引用关系。对于这样的一个简单游戏,用这种方式得到引用比较简单粗暴点。
点击Compile并关闭蓝图编辑器。按下Play测试下刚实现的重玩按钮吧!
你能够在这里下载完整项目。
如今你已经有了一个简单可玩的游戏,试着在此基础进一步完善丰富游戏。好比按玩家穿越了多少障碍点来进行计分。
你也能够尝试制做像Pong或俄罗斯方块这样的经典游戏。这些游戏机制都很简单,但实现起来都有必定难度。
若是你还想继续学习引擎其余内容,点击下篇教程,讲解如何在游戏中利用蓝图实现角色动画。