隧道
1.推动玩家前进
1.创建偏移量
- 在
BP_Player蓝图中创建一个命名为ForwardSpeed的变量,并将其初始值设置为2000 - 将
**Forward**和**Delta Seconds**相乘,获得与帧率无关的偏移量 -
2.沿单轴移动
要移动播放器,需要创建一个
**AddActorWorldffset**节点,设置**Sweep**为**True**- 将
Float结果与Delta Location相连时,虚幻引擎会自动将其转换成Vector/向量 
- Float 值会放入 Vector 的X、Y、Z分量中。因为此游戏中,前进运动只沿X轴移动,因此需要对其进行
**Split Struct Pin**操作,此时**Delta Location**引脚不能有连接。 

回顾:
创建一个以
Actor类为父类的蓝图,将其命名为**BP_TunnelSpawner**创建一个函数以在提供的位置不断生成隧道,将其命名为
**SpawnTunnel**1.创建
Spawn Tunnel的Entry节点:- 若要将位置传递给函数,该函数需要一个
**input parameter/输入参数**,调用这个函数时,这些引脚将显示为输入引脚,该参数还将作为输入引脚在Spawn Tunel函数的Entry节点 

- 创建
Spawn Tunnel的Entry节点并命名为**SpawnLocation**,设置为Vector类型 -
2.设置生成隧道及其生成位置:
添加
**Spawn Actor for class**节点,并为其选择**BP_Tunnel**类来生成隧道- 选择
**Spawn Transform**引脚,对其进行**Split Struct Pin**操作,并将其与**Entry**节点进行链接。 
- 完成该操作后,每次调用
**SpawnTunnel**函数时,该函数将在提供的位置生成一个**BP_Tunnel**实例
- 若要将位置传递给函数,该函数需要一个
测试隧道生成器
1.创建触发区域
- 在蓝图文件夹中打开
BP_Tunnel,并添加Box Collision组件并为其命名为**TriggerZone/触发区** - 由于目前碰撞区域很小,因此选中
**TriggerZone**组件,并将其**Shape**—**Box Extent/盒体范围**设置为(32, 500, 500) - 将位置属性设置为(2532, 0, 0),这会将
**TriggerZone**放在隧道网格的末端。即:当玩家到达隧道尽头时,才会生成新的隧道。 -
2.创建生成点
要定义生成点的位置,可以使用
**Scene**组件,因为这些组件只包含了转换,在视窗中也可见。- 向
BP_Tunnel中的物体添加Scene组件,并将其重命名为SpawnPoint - 由于隧道网格在X轴上的长度为2500单位,因此连接点也应当在该处,将其位置属性设置为 (2500, 0, 0)
-
3.生成点的生成隧道
下一个
BP_Tunnel应该在最远隧道的SpawnPoint生成,这样隧道将始终继续。
- 由于最远的隧道始终是最后生成的隧,因此对其获取引用即可。
- 通过下图操作创建变量,并将其重命名为
Newest Tunnel,完成链接。此时将始终对最远的隧道进行引用 
- 创建一个新函数,并将其命名为
**SpawnTunnelAtSpawnPoint**,创建以下图形。该操作将获得最新的隧道及其**SpawnPoint**组件的位置,然后由**Spawn Tunnel**在此位置生成一个新的隧道。 
为
BP_Tunnel与BP_TunnelSpawner进行通信,需要一个引用4.创建对
Tunnel Spawner的引用在
BP_Tunnel,添加一个新变量,将其重命名为Tunnel Spawner,将其变量类型设置为BP_TunnelSpawner,并将其变量类型设置为BP_TunnelSpawn\对象引用
- 在
BP_TunnelSpawner,打开Spawn Tunnel的Graph并添加以下节点 
-
5.编写触发区域脚本
在
BP_Tunnel中添加OnComponentBeginOverlap事件,当Other Actor与TriggerZone重叠时,此节点开始执行。

- 首先,需要检查穿过
**TriggerZone**是否是玩家 - 拖动
Other Actor引脚,选择Cast to BP_Player:由于另一条隧道在另一条隧道末端生成,因此它将触发该隧道的TriggerZone,如果Other Actor是Tunnel,则强转化成BP_Player将阻止任何其他节点执行。 -
4.生成更多隧道
1.创建一定数量隧道的函数
打开
**BP_TunnelSpawner**并创建一个名为**SpawnInitialTunnels**的新函数
要生成指定数量的隧道,可以使用Forloop节点。此节点将执行连接的节点指定的次数,要使**ForLoop**节点执行n次,**Last Index**需要设置为n-1次。添加一个ForLoop节点并将其连接到Entry节点。
当游戏开始时,玩家应始终在隧道中启动,因此需要在玩家的位置生成第一条隧道。2.生成第一条隧道
要确定是否生成了第一条隧道,可以检查是否设置了
**Newest Tunnel**。如果未设置,则表示尚未生成第一个隧道。这是因为**Newest Tunnel**是在游戏生成隧道之后才设置的- 要执行此检查,请在
**ForLoop**之后添加**IsValid**节点,并获取对**Newest Tunnel**的引用,将其连接到**Isvalid**节点的输入对象节点 - 如果未设置
**Newest Tunnel**,则执行Is not Valid引脚,反之亦然,添加以下内容并完成链接。 
-
3.生成后续隧道
添加一个
**Spawn Tunnel at Spawn Point**节点,并将其连接到**Isvalid**节点的**Is Valid**引脚
1.ForLoop 节点总共将执行三次 2.在第一个循环中,它将在玩家的位置生成一条隧道 3.在随后的循环中,它将在最新隧道的
Spawn Point生成隧道在
Event Graph并删除Spawn Point节点,在Event BeginPlay之后添加一个Spanw Initial Tunnel节点。 完成操作。这样在游戏开始时,将会生成三个隧道
障碍
1.制造障碍


- 打开
**BP_Tunnel**,在Components面板添加一个Static Mesh组件并将其命名为WallMesh,并在Details将其更改为SM_Hole_01,位置更改为2470, 0, 0 - 添加一个新的Float变量并将其命名为
**RotateSpeed**,默认值设为30 - 在
Event Graph创建以下设置,使Wall Mesh按提供的量进行旋转
1.创建墙变体
- 需求:无需为每个变体创建新的蓝图,完成对
WallMesh的随机化 - 在
BP_Tunnel中创建一个名为RandomizeWall的新函数,并对其与**Set Static Mesh**节点连接,该节点会将**WallMesh**设置为提供的网格体 - 使用
**Select**节点创建静态网格体列表 
**Select**节点允许设置选项列表,而**Index**输入则确定**Select**节点输出的选项-
2.随机化墙体
可以通过
**Random Integer in Range**节点来获取随机数,此节点将返回一个值,该值的取值范围为(Min, Max),因此将其设置为(0, 3),这将为其提供 0, 1,2, 3这四个值。
- 添加
Random Float in Range和AddLocalRotation节点,并拆分引脚,为WellMesh添加 0和360之间的随机旋转 
- 总结:
**Select**节点提供网格列表- 使用
**Random Integer in Range**节点选择随机网格 Set Static Mesh节点将WallMesh设置为所选网格体AddLocalRotation节点向WallMesh添加随机旋转偏移量
2.处理墙壁碰撞
如果启用或禁止向前移动,可以使用布尔变量,布尔变量只有真或假的状态。
- 在
**BP_Player**中,创建名为**IsDead**的布尔变量。在**Event Tick**节点创建**Branch**分支节点,获取对**Isdead**的引用,并将其连接到**Branch**节点的条件引脚 
完成以上连接,每当
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**节点完成相连 
-
2.显示重新启动按钮
显示的控件为
**WBP_Restart**,可以在UI文件夹中找到 要显示或隐藏控件,需要对其进行引用。打开
BP_Player,并创建名为RestarWidget类型的变量,将其变量类型更改为**WBP_Restart**的**object Refence**- 添加
Create Widget并将类值设置为WBP_Restart,添加Set Restart Widget组件节点,完成以下连接。 
- 当玩家生成时,将会创建
WBP_Restart实例

- 创建
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的函数。- 完成以下连接

Set Isdead将Isdead设置为False,这将重新启用向前移动Remove from Parent从屏幕中删除Restart WidgetSet Input Mode Game Only使游戏重新启用游戏输入,以便玩家可以四处走动Set Show Mouse Cursor设置隐藏鼠标光标。
打开BP_TunnelSpawner并确保位于SpawnlnitialTunnel事件图中。
- 需要在产生新的隧道之前移除现有的隧道
- 在
Entry节点后面添加一个Sequence节点,并将Then 1引脚连接到Forloop节点 **Sequence/序列**节点按顺序执行其输出
- 创建以下节点:此设置将获取所有隧道并将其从游戏中移除

- 将
Sequence节点的Then 0引脚连接到Get All Actors Of Class节点。这将确保在生成过程之前移除隧道。 
1.处理按钮点击
- 打开
WBP_Restart,在Eent Graph中点击RestartButton按钮,创建OnCliked。当玩家单机OnCliked(RestartButton)时,此节点开始执行 
Get Owning Player Pawn返回当前玩家控制的PawnCast To BP_Player检查Pawn是否属于BP_Player,如果是,它就会调用RestartGame函数,这个函数将会重置玩家并隐藏重启按钮。Get All Actors Class设置Actor Class为BP_TunnelSpawn,然后调用SpawnInitalTuneles,这个函数将删除现有的隧道并产生新的隧道。Get(a copy)
补充
1.ForLoop
Forloop是利用counter所具备的计算循环次数功能来进行处理的
ForLoop节点需要对计数器的初始值、结束值、循环处理、下一步进行的处理等进行设置。
ForLoop节点的输入项:exec输入项:用于连接执行顺序的顺序。First Index:为Counter设置的初始值。进入该节点后,计数器被设置为该First Index的值Last Index:计数器的结束值。计数器每循环一次就+1,当到达该Last Index值后,执行完循环处理后,直接进入之后的处理中。
ForLoop节点的输出项:变量可以
Details界面修改参数信息,将变量数据修改成Int类型,并将变量更改为数组
- 编译完成后,继续在
Details面板中Default处单击+号为数组创建初始值 -
3.ForEachLoop节点
**ForEachLoop**节点是用于处理数组的专用节点,其输入输出项也是结合数组由ForLoop演变而来

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

