关卡切换
前言
UE4 中主要有两种转移方式:无缝和非无缝方式
我们平时用的最多的OpenLevel
节点就是非无缝的, 本文主要对这些方式记录一番
OpenLevel
这是我们最常用的关卡切换的方法, 本质上都是从客户端调用了GEngine->SetClientTravel()
函数, 然后到下一帧的时候调用 UEngine::Browse()
UEngine::Browse
- 就像是加载新地图时的硬重置。
- 将始终导致非无缝切换。
- 将导致服务器在切换到目标地图前与当前客户端断开连接。
- 客户端将与当前服务器断开连接。
- 专用服务器无法切换至其他服务器,因此地图必须存储在本地(不能是 URL)。
引用官网的一段话来解释这个方法
UWorld::ServerTravel
此方式为无缝切换
先引用一个端官网的话
- 仅适用于服务器。
- 会将服务器跳转到新的世界/场景。
- 所有连接的客户端都会跟随。
- 这就是多人游戏在地图之间转移时所用的方法,而服务器将负责调用此函数。
- 服务器将为所有已连接的客户端玩家调用
APlayerController::ClientTravel
。
比如多个玩家在完成连接了以后一起下副本就需要使用此方法讲所有人一起传送到指定关卡中, 不然就断开了
此方法需要cpp的支持, 纯蓝图无法完成这个操作;
库
蓝图无法调用这个方法, 我们先封装一个函数库
1 | bool UFlib_Utilities::ServerTravel(const UObject* WorldContextObject, const FString& InURL, bool bAbsolute, bool bShouldSkipGameNotify) |
GameMode
首先要开启传送选项
1 | bUseSeamlessTravel = true; |
然后需要重写如下方法
1 | virtual void GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList) override; |
为了方便蓝图扩展, 我们声明一个蓝图方法来添加额外的传送对象
1 | UFUNCTION(BlueprintImplementableEvent) |
- 最终形态
1 | AUtilityGameModeBase::AUtilityGameModeBase() |
PlayerController
服务器将为所有已连接的客户端玩家调用
APlayerController::ClientTravel
。
所以在玩家控制器里, 同样有方法支持传送目标
- 最终形态
1 | void AMyPlayerController::GetSeamlessTravelActorList(bool bToEntry, TArray<class AActor*>& ActorList) |
过渡地图
我们可以在项目设置里设置一个过渡地图, 不过因为这个地图就一瞬间就完成了, 个人觉得意义不大
总结
- 只有服务端可以发起传送
- 玩家和玩家控制器会默认传送
- 多数状态(变量)不会传送,
BeginPlay()
等会重新执行一遍 - 测试发现对新创建的对象的静态模型修改材质/Scale3D等会传送到新关卡
- 玩家模型修改材质\Scale或者修改动画状态都无法传送到新关卡(问号脸)
- 如果是放置/Spawn在世界空间的对象, 传送以后会出现在相同位置
- Attach等操作无法传送, 如果一把武器在0点创建后Attach到玩家手上并添加到传送列表,传送以后还是出现在0点并不会Attach到玩家手上
- 对于GameMode的传送对象, 如果未开启同步, 那么只会在服务端传送
- 对于PlayerController的传送对象, 如果未开启同步, 只会在本地传送
测试
- 服务端创建cube
- 客户端创建sphere
- 创建5秒以后修改scale和材质为红色
- 传送以后颜色和scale传递了过去
- 修改玩家模型的材质和缩放
- 无法传送这些状态