隧道

1.推动玩家前进

1.创建偏移量

  • BP_Player蓝图中创建一个命名为ForwardSpeed的变量,并将其初始值设置为2000
  • **Forward****Delta Seconds**相乘,获得与帧率无关的偏移量
  • image.png

    2.沿单轴移动

  • 要移动播放器,需要创建一个**AddActorWorldffset**节点,设置**Sweep****True**

  • Float结果与Delta Location相连时,虚幻引擎会自动将其转换成Vector/向量
  • image.png
  • Float 值会放入 Vector 的X、Y、Z分量中。因为此游戏中,前进运动只沿X轴移动,因此需要对其进行**Split Struct Pin**操作,此时**Delta Location**引脚不能有连接。
  • image.pngimage.png
  • 回顾:

    • 每一帧中,游戏都将**Forward Speed/前进速度****Delta Seconds/增量秒**相乘,得到和帧率无关的运动结果。Forward Speed的默认值被设置为2000。
    • **AddActorWorldOffset**将该运动结果沿X轴移动**Player**
    • 因为启动了**Sweep**,因此在被障碍物阻挡时,玩家将停止移动

      2.创建隧道生成器

  • 创建一个以Actor类为父类的蓝图,将其命名为**BP_TunnelSpawner**

  • 创建一个函数以在提供的位置不断生成隧道,将其命名为**SpawnTunnel**

    1.创建Spawn TunnelEntry节点:

    • 若要将位置传递给函数,该函数需要一个**input parameter/输入参数**调用这个函数时,这些引脚将显示为输入引脚,该参数还将作为输入引脚在Spawn Tunel函数的Entry节点
    • image.pngimage.png
    • 创建Spawn TunnelEntry节点并命名为**SpawnLocation**设置为Vector类型
    • image.png

      2.设置生成隧道及其生成位置:

    • 添加**Spawn Actor for class**节点,并为其选择**BP_Tunnel**类来生成隧道

    • 选择**Spawn Transform**引脚,对其进行**Split Struct Pin**操作,并将其与**Entry**节点进行链接。
    • image.png
    • 完成该操作后,每次调用**SpawnTunnel**函数时,该函数将在提供的位置生成一个**BP_Tunnel**实例
  • 测试隧道生成器

    • **BP_TunnelSpawner**—>**Event Graph**中找到**Event BeginPlay**,添加**Spawn Tunnel**节点使二者相连,并将**Spawn Tunnel**节点更改生成位置
    • image.png
    • Level中删除BP_Tunnel,并将BP_TunnelSpawner添加到Viewport完成实例化。
    • 运行play时,游戏会在玩家上方产生一条隧道

      3.设置隧道蓝图

      **BP_Tunnel**负责两个功能:

    • 检测游戏何时应该生成新的隧道:创建一个触发区域,每次触发时,由**BP_TunnerlSpawner**生成一个新的隧道。

    • 定义一个生成点:**BP_TunnelSpawner**使此点作为下一个生成位置

05-虚幻引擎4:游戏教程 - 图10

1.创建触发区域

  • 在蓝图文件夹中打开BP_Tunnel,并添加Box Collision组件并为其命名为**TriggerZone/触发区**
  • 由于目前碰撞区域很小,因此选中**TriggerZone**组件,并将其**Shape****Box Extent/盒体范围**设置为(32, 500, 500)
  • 将位置属性设置为(2532, 0, 0),这会将**TriggerZone**放在隧道网格的末端。即:当玩家到达隧道尽头时,才会生成新的隧道。
  • image.png

    2.创建生成点

  • 要定义生成点的位置,可以使用**Scene**组件,因为这些组件只包含了转换,在视窗中也可见。

  • BP_Tunnel中的物体添加Scene组件,并将其重命名为SpawnPoint
  • 由于隧道网格在X轴上的长度为2500单位,因此连接点也应当在该处,将其位置属性设置为 (2500, 0, 0)
  • image.png

    3.生成点的生成隧道

  • 下一个BP_Tunnel应该在最远隧道的SpawnPoint生成,这样隧道将始终继续。

  • 05-虚幻引擎4:游戏教程 - 图13
  • 由于最远的隧道始终是最后生成的隧,因此对其获取引用即可。
  • 通过下图操作创建变量,并将其重命名为Newest Tunnel,完成链接。此时将始终对最远的隧道进行引用
  • image.png
  • 创建一个新函数,并将其命名为**SpawnTunnelAtSpawnPoint**,创建以下图形。该操作将获得最新的隧道及其**SpawnPoint**组件的位置,然后由**Spawn Tunnel**在此位置生成一个新的隧道。
  • image.png
  • BP_TunnelBP_TunnelSpawner进行通信,需要一个引用

    4.创建对Tunnel Spawner的引用

  • BP_Tunnel,添加一个新变量,将其重命名为Tunnel Spawner,将其变量类型设置为BP_TunnelSpawner,并将其变量类型设置为BP_TunnelSpawn\对象引用

  • image.png
  • BP_TunnelSpawner,打开Spawn Tunnel的Graph并添加以下节点
  • image.png
  • 每个隧道都将对BP_TunnelSpawner的引用

    5.编写触发区域脚本

  • BP_Tunnel中添加OnComponentBeginOverlap事件,当Other ActorTriggerZone重叠时,此节点开始执行。

image.png

  • 首先,需要检查穿过**TriggerZone**是否是玩家
  • 拖动Other Actor引脚,选择Cast to BP_Player:由于另一条隧道在另一条隧道末端生成,因此它将触发该隧道的TriggerZone,如果Other Actor是Tunnel,则强转化成BP_Player将阻止任何其他节点执行。
  • image.png

    4.生成更多隧道

    1.创建一定数量隧道的函数

    打开**BP_TunnelSpawner**并创建一个名为**SpawnInitialTunnels**的新函数
    要生成指定数量的隧道,可以使用Forloop节点。此节点将执行连接的节点指定的次数,要使**ForLoop**节点执行n次,**Last Index**需要设置为n-1次。添加一个ForLoop节点并将其连接到Entry节点。
    image.png
    当游戏开始时,玩家应始终在隧道中启动,因此需要在玩家的位置生成第一条隧道。

    2.生成第一条隧道

  • 要确定是否生成了第一条隧道,可以检查是否设置了**Newest Tunnel**如果未设置,则表示尚未生成第一个隧道。这是因为**Newest Tunnel**是在游戏生成隧道之后才设置的

  • 要执行此检查,请在**ForLoop**之后添加**IsValid**节点,并获取对**Newest Tunnel**的引用,将其连接到**Isvalid**节点的输入对象节点
  • 如果未设置**Newest Tunnel**则执行Is not Valid引脚,反之亦然,添加以下内容并完成链接。
  • image.png
  • 该设置将在玩家Pawn的位置生成一条隧道。

    3.生成后续隧道

  • 添加一个**Spawn Tunnel at Spawn Point**节点,并将其连接到**Isvalid**节点的**Is Valid**引脚

  • image.png

    1.ForLoop 节点总共将执行三次 2.在第一个循环中,它将在玩家的位置生成一条隧道 3.在随后的循环中,它将在最新隧道的Spawn Point生成隧道

  • Event Graph并删除Spawn Point节点,在Event BeginPlay之后添加一个Spanw Initial Tunnel节点。 完成操作。这样在游戏开始时,将会生成三个隧道


障碍

1.制造障碍

image.pngimage.png

  1. 打开**BP_Tunnel**,在Components面板添加一个Static Mesh组件并将其命名为WallMesh,并在Details将其更改为SM_Hole_01,位置更改为2470, 0, 0
  2. 添加一个新的Float变量并将其命名为**RotateSpeed**,默认值设为30
  3. Event Graph创建以下设置,使Wall Mesh按提供的量进行旋转

image.png

1.创建墙变体

  • 需求:无需为每个变体创建新的蓝图,完成对WallMesh的随机化
  • BP_Tunnel中创建一个名为RandomizeWall的新函数,并对其与**Set Static Mesh**节点连接,该节点会将**WallMesh**设置为提供的网格体
  • 使用**Select**节点创建静态网格体列表
  • image.png
  • **Select**节点允许设置选项列表,而**Index**输入则确定**Select**节点输出的选项
  • 添加两个Option引脚,并将其选项内容设置为不同元素

    2.随机化墙体

  • 可以通过**Random Integer in Range**节点来获取随机数,此节点将返回一个值,该值的取值范围为(Min, Max),因此将其设置为(0, 3),这将为其提供 0, 1,2, 3这四个值。

  • image.png
  • 添加Random Float in RangeAddLocalRotation节点,并拆分引脚,为WellMesh添加 0360之间的随机旋转
  • image.png

  • 总结:
    • **Select**节点提供网格列表
    • 使用**Random Integer in Range**节点选择随机网格
    • Set Static Mesh节点将WallMesh设置为所选网格体
    • AddLocalRotation节点向WallMesh添加随机旋转偏移量

2.处理墙壁碰撞

如果启用或禁止向前移动,可以使用布尔变量,布尔变量只有的状态

  • **BP_Player**中,创建名为**IsDead**的布尔变量。在**Event Tick**节点创建**Branch**分支节点,获取对**Isdead**的引用,并将其连接到**Branch**节点的条件引脚
  • image.png
  • 完成以上连接,每当Isadead设置为True时,玩家停止前进。当玩家撞墙时设置Isdead变量、

    1.设置 Isdead 变量

  • 创建**WallMesh****On Component Hit**事件,每当另一个**Actor****WallMesh**发生碰撞时,此节点执行。

  • 首先需要检查**WallMesh**碰撞的**Actor**是否是玩家
  • 拖动**Other Actor**节点,将其与**Cast To BP_Player**相连
  • 添加**Set Isdead**节点,并勾选复选框将**Isdead**设置为True,与**Cast To BP_Player**节点完成相连
  • image.png
  • 编译完成后,游戏将在触碰障碍后不再进行下落运动。

    2.显示重新启动按钮

    显示的控件为**WBP_Restart**可以在UI文件夹中找到

  • 要显示或隐藏控件,需要对其进行引用。打开BP_Player,并创建名为RestarWidget类型的变量,将其变量类型更改为**WBP_Restart****object Refence**

  • 添加Create Widget并将类值设置为WBP_Restart,添加Set Restart Widget组件节点,完成以下连接。
  • image.png
  • 当玩家生成时,将会创建WBP_Restart实例

image.png

  • 创建Display Restart函数,并添加Add to Viewport节点以显示Restart Widget
  • Set Input Mode UI Only将限制玩家对UI的交互
  • Set Show Mouse Cursor将对鼠标进行控制:显示或隐藏
  • 要显示重新启动按钮,应当在播放器和墙壁碰撞后调用DisplayRestart
  • 切换到BP_Tunnel,将DisplayRestart节点添加到On Component Hit(WallMesh)节点链的末尾。此后发生碰撞时,将出现重新启动按钮。

    重新启动游戏

  • 打开BP_Player,创建名为RestartGame的函数。

  • 完成以下连接
  • image.png
  • Set IsdeadIsdead设置为False,这将重新启用向前移动
  • Remove from Parent从屏幕中删除Restart Widget
  • Set Input Mode Game Only使游戏重新启用游戏输入,以便玩家可以四处走动
  • Set Show Mouse Cursor设置隐藏鼠标光标。

打开BP_TunnelSpawner并确保位于SpawnlnitialTunnel事件图中。

  • 需要在产生新的隧道之前移除现有的隧道
  • Entry节点后面添加一个Sequence节点,并将Then 1引脚连接到Forloop节点
  • **Sequence/序列**节点按顺序执行其输出
  • image.png
  • 创建以下节点:此设置将获取所有隧道并将其从游戏中移除
  • image.png
  • Sequence节点的Then 0引脚连接到Get All Actors Of Class节点。这将确保在生成过程之前移除隧道。
  • image.png

1.处理按钮点击

  • 打开WBP_Restart,在Eent Graph中点击RestartButton按钮,创建OnCliked。当玩家单机OnCliked(RestartButton)时,此节点开始执行
  • image.png
  • Get Owning Player Pawn返回当前玩家控制的Pawn
  • Cast To BP_Player检查Pawn是否属于BP_Player,如果是,它就会调用RestartGame函数,这个函数将会重置玩家并隐藏重启按钮。
  • Get All Actors Class设置Actor ClassBP_TunnelSpawn,然后调用SpawnInitalTuneles,这个函数将删除现有的隧道并产生新的隧道。
  • Get(a copy)

补充

1.ForLoop

  • Forloop是利用counter所具备的计算循环次数功能来进行处理的
  • image.png
  • ForLoop节点需要对计数器的初始值、结束值、循环处理、下一步进行的处理等进行设置。
  • image.png
  • ForLoop节点的输入项:
    • exec输入项:用于连接执行顺序的顺序。
    • First Index:为Counter设置的初始值。进入该节点后,计数器被设置为该First Index的值
    • Last Index:计数器的结束值。计数器每循环一次就+1,当到达该Last Index值后,执行完循环处理后,直接进入之后的处理中。
  • ForLoop节点的输出项:

    • Loop Body:用于连接循环所执行的处理
    • Index:取出当前计数器的值
    • Completed:连接循环完成后的处理

      2.数组

      数组是一种特别的值,可对多个值进行集中管理。处理保管于数组中的所有数据时会用到循环,如利用敌人角色的数组使他们同时动作。
      而处理数组中的所有元素,可以使用ForEachLoop循环,该节点是专门用于处理FoorLop循环。传递数组后,可按顺序从数组中取出值并进行处理。
  • 变量可以Details界面修改参数信息,将变量数据修改成Int类型,并将变量更改为数组

  • image.png
  • 编译完成后,继续在Details面板中Default处单击+号为数组创建初始值
  • image.png

    3.ForEachLoop节点

  • **ForEachLoop**节点是用于处理数组的专用节点,其输入输出项也是结合数组由ForLoop演变而来

  • image.pngimage.png
  • ForEachLoop节点的输入项:
    • Exec:处理执行处理的顺序
    • Array:连接要处理的数组
  • ForEachLoop节点的输出项:
    • Loop Body:将循环处理的内容连接至此以创建处理
    • Array Element:在ForEachLoop中将以顺序从数组中取出值,所取出的值将从此处获得
    • Array Index:可获得取出值的Index编号
    • Completed:数组处理完后,用于连接至后续的处理