虚幻引擎(UE5)携带Actor过关卡(附工程源码)

前言

虚幻引擎在定义关卡时,将关卡设定为是一个World,从关卡类型可以得知UWorld类型。一个世界具备一个世界的规则。两个不同的关卡可以使用相同的规则,但是不是同一个规则。就如同我们的法律中规定盗窃是犯罪,其他国家一样也有这样的法律规则。

并且虚幻引擎在一定意义上不允许有两个世界同时存在,所以当我们切换关卡时,旧有的关卡对象必然会被释放掉!而新关卡对象与旧有关卡无关。

那是否可以携带旧有关卡中的对象到新关卡呢?答案是可以的!只不过我们需要借助虚幻引擎中的无缝漫游设置。

注意:蓝图无法直接实现,需要依赖C++

步骤

1、开启无缝漫游,需要在Gamemode的代码中设置,或是在Gamemode蓝图面板中设置(二选一)。

ACarryThroughGameModeBase::ACarryThroughGameModeBase()
{
	//应用无缝漫游 Gamemode构造函数中设置
	bUseSeamlessTravel = true;
}

或是在面板中设置

2、C++中Gamemode重写父类GetSeamlessTravelActorList函数

virtual void GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList) override;

大家需要注意,此函数在切换关卡使用无缝漫游时会被调用,调用时,需要将漫游过关卡的Actor添加到参数ActorList中,即可将Actor携带过关。

实现代码参照

void ACarryThroughGameModeBase::GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList)
{
	//需要优先调用,蓝图传入会覆盖ActorList
	K2_GetSeamlessTravelActorList(ActorList);
	//将自身存储数组数据追加到List数组中
	ActorList.Append(TravelActorList);
	//必须调用父类函数
	Super::GetSeamlessTravelActorList(bToTransition, ActorList);
}

其中K2_GetSeamlessTravelActorList是我添加的函数,用于向蓝图暴露,蓝图可重写,函数声明如下

UFUNCTION(BlueprintImplementableEvent, DisplayName="GetSeamlessTravelActorList")
void K2_GetSeamlessTravelActorList(TArray<AActor*>& ActorList);

TravelActorList是我在GameMode中添加的用来存储保存过关Actor的数组。

ACarryThroughGameModeBase.h源码

#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源码

#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

3、启动切换关卡

切换关卡时注意需要独立进程启动,并且不要使用Openlevel节点!可使指令节点,启用无缝切换地图。

指令命令参照(注意分割空格):ServerTravel /Game/Maps/l02

也可以在C++中调用代码切换,源码结构如下:

/**
	 * 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

添加评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注