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

前言

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

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

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

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

步骤

  1. 开启无缝漫游,需要在Gamemode的代码中设置,或是在Gamemode蓝图面板中设置(二选一)。
1ACarryThroughGameModeBase::ACarryThroughGameModeBase()
2{
3    //应用无缝漫游 Gamemode构造函数中设置
4    bUseSeamlessTravel = true;
5}

或是在继承Gamemode的蓝图类面板中设置

GameMode细节面板

  1. C++中Gamemode重写父类GetSeamlessTravelActorList函数
1virtual void GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList) override;

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

实现代码参照

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

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

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

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

ACarryThroughGameModeBase.h源码

 1#pragma once
 2 
 3#include "CoreMinimal.h"
 4#include "GameFramework/GameModeBase.h"
 5#include "CarryThroughGameModeBase.generated.h"
 6 
 7/**
 8 * 
 9 */
10UCLASS()
11class CARRYTHROUGH_API ACarryThroughGameModeBase : public AGameModeBase
12{
13    GENERATED_BODY()
14 
15 
16    ACarryThroughGameModeBase();
17     
18protected:
19 
20    virtual void GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList) override;
21 
22    UFUNCTION(BlueprintCallable)
23    void AddTravelActorList(AActor* Actor);
24    UFUNCTION(BlueprintImplementableEvent, DisplayName="GetSeamlessTravelActorList")
25    void K2_GetSeamlessTravelActorList(TArray<AActor*>& ActorList);
26 
27protected:
28     
29    UPROPERTY()
30    TArray<AActor*> TravelActorList;
31};

ACarryThroughGameModeBase.cpp源码

 1#include "CarryThroughGameModeBase.h"
 2 
 3ACarryThroughGameModeBase::ACarryThroughGameModeBase()
 4{
 5    //应用无缝漫游
 6    bUseSeamlessTravel = true;
 7}
 8 
 9void ACarryThroughGameModeBase::GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList)
10{
11    //需要优先调用,蓝图传入会覆盖ActorList
12    K2_GetSeamlessTravelActorList(ActorList);
13    //将自身存储数组数据追加到List数组中
14    ActorList.Append(TravelActorList);
15    //必须调用父类函数
16    Super::GetSeamlessTravelActorList(bToTransition, ActorList);
17}
18 
19void ACarryThroughGameModeBase::AddTravelActorList(AActor* Actor)
20{
21    TravelActorList.Add(Actor);
22}

蓝图中重写函数截图

BP_Gaemode继承自ACarryThroughGameModeBase

  1. 启动切换关卡 切换关卡时注意需要独立进程启动,并且不要使用Openlevel节点!可使指令节点,启用无缝切换地图。
    指令命令参照(注意分割空格):ServerTravel /Game/Maps/l02

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

1/**
2     * Jumps the server to new level.  If bAbsolute is true and we are using seemless traveling, we
3     * will do an absolute travel (URL will be flushed).
4     *
5     * @param URL the URL that we are traveling to
6     * @param bAbsolute whether we are using relative or absolute travel
7     * @param bShouldSkipGameNotify whether to notify the clients/game or not
8     */
9bool ServerTravel(const FString& InURL, bool bAbsolute = false, bool bShouldSkipGameNotify = false);

源码位置:UWorld

效果展示

原始关卡
新关卡

切换后Actor原有状态不变,数据不变。在一些设计中,仍需要考虑携带过关的Actor是否会关联其他对象,关联对象是否要被携带过关,所以这也是一个复杂的设计。

工程链接:传送门

提取码:2gcl

引擎版本: 5.1

文章评论