Preface

When defining a level, Unreal Engine sets the level as a World. The UWorld type can be known from the level type. A world has its own rules. Two different levels can use the same rules, but they are not the same rules. Just as our laws stipulate that theft is a crime, other countries also have such legal rules.

And Unreal Engine does not allow two worlds to exist at the same time in a certain sense, so when we switch levels, the old level objects will inevitably be released! And the new level objects have nothing to do with the old level.

So can we carry objects from the old level to the new level? The answer is yes! But we need to use the seamless roaming settings in Unreal Engine.

Note: Blueprint cannot be implemented directly, and needs to rely on C++

Steps

  1. To enable seamless roaming, you need to set it in the Gamemode code or in the Gamemode blueprint panel (choose one of the two).
c++
1
2
3
4
5
ACarryThroughGameModeBase::ACarryThroughGameModeBase()
{
    //Set in the Gamemode constructor to apply seamless roaming
    bUseSeamlessTravel = true;
}

Or set in the blueprint class panel that inherits Gamemode

GameMode details panel
GameMode details panel

  1. Gamemode overrides the parent class GetSeamlessTravelActorList function in C++
c++
1
virtual void GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList) override;

Note that this function will be called when seamless roaming is used when switching levels. When calling, the Actor that roams through the level needs to be added to the parameter ActorList, so that the Actor can be carried through the level.

Implementation code reference

c++
1
2
3
4
5
6
7
8
9
void ACarryThroughGameModeBase::GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList)
{
    //Need to be called first, blueprint input will overwrite ActorList
    K2_GetSeamlessTravelActorList(ActorList);
    //Append the self-stored array data to the List array
    ActorList.Append(TravelActorList);
    //Must call the parent class function
    Super::GetSeamlessTravelActorList(bToTransition, ActorList);
}

K2_GetSeamlessTravelActorList is the function I added, which is used to expose to the blueprint. The blueprint can be overwritten. The function declaration is as follows

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

TravelActorList is the array I added in GameMode to store the Actors that have passed the level.

ACarryThroughGameModeBase.h source code

c++
 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 source code

c++
 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()
{
    //Apply seamless roaming
    bUseSeamlessTravel = true;
}

void ACarryThroughGameModeBase::GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList)
{
    //Need to be called first, the blueprint will overwrite ActorList
    K2_GetSeamlessTravelActorList(ActorList);
    //Append the self-stored array data to the List array
    ActorList.Append(TravelActorList);
    //Must call parent class function
    Super::GetSeamlessTravelActorList(bToTransition, ActorList);
}

void ACarryThroughGameModeBase::AddTravelActorList(AActor* Actor)
{
    TravelActorList.Add(Actor);
}

Screenshot of overriding function in blueprint

BP_Gaemode inherits from ACarryThroughGameModeBase
BP_Gaemode inherits from ACarryThroughGameModeBase

  1. Start switching levels When switching levels, please note that an independent process needs to be started, and do not use the Openlevel node! You can use the command node to enable seamless map switching.
    Command reference (note the separator space): ServerTravel /Game/Maps/l02

You can also call code switching in C++, the source code structure is as follows:

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);

Source code location: UWorld

Effect display

Original level
Original level
New level
New level

After switching, the original state of the Actor remains unchanged, and the data remains unchanged. In some designs, it is still necessary to consider whether the Actor that carries through the level will be associated with other objects, and whether the associated objects will be carried through the level, so this is also a complex design.

Project link: Portal

Extraction code: 2gcl

Engine version: 5.1