前言
虚幻引擎在定义关卡时,将关卡设定为是一个World,从关卡类型可以得知UWorld类型。一个世界具备一个世界的规则。两个不同的关卡可以使用相同的规则,但是不是同一个规则。就如同我们的法律中规定盗窃是犯罪,其他国家一样也有这样的法律规则。
并且虚幻引擎在一定意义上不允许有两个世界同时存在,所以当我们切换关卡时,旧有的关卡对象必然会被释放掉!而新关卡对象与旧有关卡无关。
那是否可以携带旧有关卡中的对象到新关卡呢?答案是可以的!只不过我们需要借助虚幻引擎中的无缝漫游设置。
注意:蓝图无法直接实现,需要依赖C++
步骤
- 开启无缝漫游,需要在Gamemode的代码中设置,或是在Gamemode蓝图面板中设置(二选一)。
1
2
3
4
5
|
ACarryThroughGameModeBase::ACarryThroughGameModeBase()
{
//应用无缝漫游 Gamemode构造函数中设置
bUseSeamlessTravel = true;
}
|
或是在继承Gamemode的蓝图类面板中设置
GameMode细节面板
- C++中Gamemode重写父类GetSeamlessTravelActorList函数
1
|
virtual void GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList) override;
|
注意,此函数在切换关卡使用无缝漫游时会被调用,调用时,需要将漫游过关卡的Actor添加到参数ActorList中,即可将Actor携带过关。
实现代码参照
1
2
3
4
5
6
7
8
9
|
void ACarryThroughGameModeBase::GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList)
{
//需要优先调用,蓝图传入会覆盖ActorList
K2_GetSeamlessTravelActorList(ActorList);
//将自身存储数组数据追加到List数组中
ActorList.Append(TravelActorList);
//必须调用父类函数
Super::GetSeamlessTravelActorList(bToTransition, ActorList);
}
|
其中K2_GetSeamlessTravelActorList是我添加的函数,用于向蓝图暴露,蓝图可重写,函数声明如下
1
2
|
UFUNCTION(BlueprintImplementableEvent, DisplayName="GetSeamlessTravelActorList")
void K2_GetSeamlessTravelActorList(TArray<AActor*>& ActorList);
|
TravelActorList是我在GameMode中添加的用来存储保存过关Actor的数组。
ACarryThroughGameModeBase.h源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "CarryThroughGameModeBase.generated.h"
/**
*
*/
UCLASS()
class CARRYTHROUGH_API ACarryThroughGameModeBase : public AGameModeBase
{
GENERATED_BODY()
ACarryThroughGameModeBase();
protected:
virtual void GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList) override;
UFUNCTION(BlueprintCallable)
void AddTravelActorList(AActor* Actor);
UFUNCTION(BlueprintImplementableEvent, DisplayName="GetSeamlessTravelActorList")
void K2_GetSeamlessTravelActorList(TArray<AActor*>& ActorList);
protected:
UPROPERTY()
TArray<AActor*> TravelActorList;
};
|
ACarryThroughGameModeBase.cpp源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#include "CarryThroughGameModeBase.h"
ACarryThroughGameModeBase::ACarryThroughGameModeBase()
{
//应用无缝漫游
bUseSeamlessTravel = true;
}
void ACarryThroughGameModeBase::GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList)
{
//需要优先调用,蓝图传入会覆盖ActorList
K2_GetSeamlessTravelActorList(ActorList);
//将自身存储数组数据追加到List数组中
ActorList.Append(TravelActorList);
//必须调用父类函数
Super::GetSeamlessTravelActorList(bToTransition, ActorList);
}
void ACarryThroughGameModeBase::AddTravelActorList(AActor* Actor)
{
TravelActorList.Add(Actor);
}
|
蓝图中重写函数截图
BP_Gaemode继承自ACarryThroughGameModeBase
- 启动切换关卡
切换关卡时注意需要独立进程启动,并且不要使用Openlevel节点!可使指令节点,启用无缝切换地图。
指令命令参照(注意分割空格):ServerTravel /Game/Maps/l02
也可以在C++中调用代码切换,源码结构如下:
1
2
3
4
5
6
7
8
9
|
/**
* Jumps the server to new level. If bAbsolute is true and we are using seemless traveling, we
* will do an absolute travel (URL will be flushed).
*
* @param URL the URL that we are traveling to
* @param bAbsolute whether we are using relative or absolute travel
* @param bShouldSkipGameNotify whether to notify the clients/game or not
*/
bool ServerTravel(const FString& InURL, bool bAbsolute = false, bool bShouldSkipGameNotify = false);
|
源码位置:UWorld
效果展示
原始关卡
新关卡
切换后Actor原有状态不变,数据不变。在一些设计中,仍需要考虑携带过关的Actor是否会关联其他对象,关联对象是否要被携带过关,所以这也是一个复杂的设计。
工程链接:传送门
提取码:2gcl
引擎版本: 5.1