下面的图是无缝与非无缝切换的流程图
文章图片
使用注意: 0.无缝和非无缝,是单机和多人游戏都存在的关卡切换形式。并不仅仅是指多人游戏。
1.无缝过程整体是异步的, url中只有map部分有效,加入viewport的UUserWidget将保留,如果联网,不会断开连接,过程中将调用UWorld::SeamlessTravel,LoadPackageAsync。
2.非无缝过程是整体或部分阻塞的,加入viewport的UUserWidget将被移除(loadmap中调用了 FWorldDelegates::LevelRemovedFromWorld.Broadcast(nullptr, WorldContext.World());
),如果联网,总会先断开之前的连接,过程中将调用UEngine::Browse、UEngine::LoadMap、LoadPackage。
3.不直接调用UEngine::Browse。进行关卡切换。
4.多人游戏的关卡切换时只建议在服务器端通过使用UWorld::ServerTravel的无缝模式进行,且此时无缝是指 传给UWorld::ServerTravel的TravelType = TRAVEL_Relative,且AGameModeBase::bUseSeamlessTravel 设置为 true。非无缝将导致服务器从调用UWorld::ServerTravel开始,NetDriver->ServerTravelPause秒(默认是4秒)后开始加载地图.且地图加载是阻塞状态。直到服务器加载完成地图后,客户端才开始进行地图加载,且加载过程也是阻塞状态。
5.APlayerController::ClientTravel (const FString& URL, ETravelType TravelType, bool bSeamless, FGuid MapPackageGuid)
1.多人游戏中建议只在连接服务器时才使用,且TravelType=TRAVEL_Absolute
2.bSeamless && TravelType == TRAVEL_Relative时,才表示无缝。且url中有效的只有map部分。可用于单人游戏状态时的异步加载地图,将使用TransitionMap 作为加载界面,注意:无缝切换过程中,transitionmap及其所包含的actor的beiginplay,endplay,以及destroy都不会被调用。
6.创建服务器监听请使用UGameplayStatics::OpenLevel,参数options使用?listen
7.UGameplayStatics::OpenLevel是非无缝的。 加入,断开服务器建议使用它。 简单的断开服务器请使用?closed作为url的选项。
URL格式 unreal://127.0.0.1:10086map2?listen
以协议开头,这个是可选的,比如http 或者 unreal,这个通常不需要。如有必须与Engine.ini中的[URL]下的Protocol相同。该[URL]标签设置作为服务器时,监听的端口,协议名称等信息。
然后后面跟冒号:,之后是可选的双斜杠//,之后是地址,地址是可选的,表示远程连接到的地址,可以是 "204.157.115.40" or "unreal.epicgames.com"两种形式,没有地址表示本地,不进行联机,注意即便写的地址是本地地址,也表示进行远程联机。再之后跟:,之后跟端口号。 在之后跟地图,地图可以是全路径的/Game/Maps/mapName,也可以是简单的地图名称mapName。再之后跟选项,每个选项以?开头,常用选项有listen,表示作为服务器使用, closed表示断开服务器。 listen时,不能使用地址和端口号(要使用指定端口号,一种方法时再[URL]标签中设置,另外一种就是以part=端口号作为命令行参数)。还有一个game,表示要指定的Gamemode,该Gamemode将代替打开关卡的默认gamemode,格式如下
game=/Game/mygamemode.mygamemode_C
等号后面是需要的gamemode文件资源,格式与loadobject相同
地址与地图不能同时使用。 有地址时,地图失效
无缝与非无缝切换 UE4 中主要有两种转移方式:无缝和非无缝方式。 两者的主要区别在于,无缝转移是一种非阻塞(non-blocking)操作,而非无缝转移则是一种阻塞(blocking)操作。
当客户端执行非无缝转移时,客户端将与服务器断开连接,然后重新连接到同一服务器,而服务器将准备新的地图以供加载。
我们建议 UE4 多人模式游戏尽量采用无缝转移
有三种情形中必然产生非无缝转移:
- 初次加载地图时
- 初次作为客户端连接服务器时
- 想要终止一个多人模式游戏并启动新游戏时
UEngine::Browse
- 就像是加载新地图时的硬重置。
- 将始终导致非无缝切换。并且所有的非无缝都调用了该函数
- 将导致服务器在切换到目标地图前与当前客户端断开连接。
- 客户端将与当前服务器断开连接。
- 专用服务器无法切换至其他服务器,因此地图必须存储在本地(不能是 URL)。
- 仅适用于服务器。
- 会将服务器跳转到新的世界/场景。
- 所有连接的客户端都会跟随。
- 这就是多人游戏在地图之间转移时所用的方法,而服务器将负责调用此函数。
- 服务器将为所有已连接的客户端玩家调用 APlayerController::ClientTravel。
- 如果从客户端调用,则转移到新的服务器
- 如果从服务器调用,则要求特定客户端转移到新地图(但仍然连接到当前服务器)
之所以存在过渡地图,是因为必须始终有一个被加载的世界(用于存放地图),所以在加载新地图之前,我们不能释放原有的地图。由于地图可能会非常大,因此让新旧地图同时存放在存储器内绝对是个坏主意,这时就需要过渡地图来帮忙了。
现在,我们可以从当前地图转移到过渡地图,然后可以从那里转移到最终的地图。由于过渡地图非常小,因此在“中转”当前地图和最终地图时不会造成太大的资源消耗。
设置好过渡地图后,您需要将 AGameModeBase::bUseSeamlessTravel 设置为 true,这样就可以实现无缝切换了!
注意:无缝切换过程中,transitionmap及其所包含的actor的beiginplay,endplay,以及destroy都不会被调用。
无缝切换流程 下面是执行无缝切换时的一般流程:
- 标记出要在过渡关卡中存留的 actor(更多信息请见下面)
- 【ue4|ue4 关卡切换】转移到过渡关卡
- 标记出要在最终关卡中存留的 actor(更多信息请见下面)
- 转移到最终关卡
默认情况下,这些 actor 将自动存留:
- GameMode actor(仅限服务器)
- 通过 AGameModeBase::GetSeamlessTravelActorList 额外添加的任何 actor
- 通过 AGameModeBase::GetSeamlessTravelActorList 额外添加的任何 actor
- 拥有一个有效的 PlayerState (仅限服务器)的所有控制器
- 所有 PlayerControllers (仅限服务器)
- 所有本地 PlayerControllers (服务器和客户端)
- 通过 APlayerController::GetSeamlessTravelActorList (在本地PlayerControllers上调用)额外添加的任何 actor
- 通过 APlayerController::GetSeamlessTravelActorList (在本地PlayerControllers上调用)额外添加的任何 actor
无缝切换时,服务器和客户端将同时通过LoadPackageAsync 异步加载地图,首先是异步加载transitionMap,然后是异步加载目的地图。 无缝切换期间,不会调用UEngine::Browse.也就不会调用Loadmap,所以不会断开连接。
非无缝切换时,服务器首先让所有客户端通过UEngine::Browse 断开原有连接,然后让客户端创建新的等待连接,从此时开始服务器不接受新的connect(UWorld::NotifyAcceptingConnection),服务器将等待 NetDriver->ServerTravelPause秒(默认是4秒)后开始加载地图。服务器加载地图完成之后开始接收新的connect。客户端的等待连接接收到新的地图信息后,开始加载地图,并将等待连接设为新的连接
推荐阅读
- 使用虚幻引擎中的C++导论
- Scripting the Editor using Python
- 虚幻4DPI自适应缩放规则解析
- 【UE4_C++】<14-3>用户界面 UI和UMG——为UI创建屏幕尺寸自适应缩放
- UE4血条、名字面向相机
- UE4|UE4C++ 设置UMG控件的Slot
- UE4|AirSim里的那些坑
- UE4总结四