level streaming for UE 5.4 and C++ - how to?

I want to figure out how to load a new level and ‘move’ my character into it when the character overlaps or enters a certain area. Im trying to follow this tutorial:

but there are a few things that i don’t understand, apparently.

I believe I’ve set up the Level window correctly:

and i’ll include my header and source files inline here.

What i expect/hope is that my character would automatically ‘spawn’ into the target level once it enters the ‘OverlapVolume’

What i see instead is that the character is ‘respawned’ at the PlayerStart of the source level and the original instance of the character is still visible stuck as they enter the OverlapVolume - very strange (kind of like this movie i just watched called ‘Triangle’ from 2009 - not a good movie, don’t watch it!).

I’m also unsure what the emphasized text below means in the tutorial:

"Place your LevelStreamer Actor into your level, and adjust the placement and scale until it encompasses the part of the persistent world you want your Character to be in to begin streaming, as well as the entire walkable volume where the streaming level will be."

thank you for any advice you can offer …

LevelStreamerActor.h

#pragma once

include “Components/BoxComponent.h”
include “GameFramework/Actor.h”
include “LevelStreamerActor.generated.h”

UCLASS()
class OFFICE_API ALevelStreamerActor : public AActor {
GENERATED_BODY()

public:
// Sets default values for this actor’s properties
ALevelStreamerActor();

// Called every frame
virtual void Tick(float DeltaSeconds) override;

protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;

UFUNCTION()
void OverlapBegins(UPrimitiveComponent *OverlappedComponent,
AActor *OtherActor, UPrimitiveComponent *OtherComp,
int32 OtherBodyIndex, bool bFromSweep,
const FHitResult &SweepResult);

UFUNCTION()
void OverlapEnds(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor,
UPrimitiveComponent *OtherComp, int32 OtherBodyIndex);

UPROPERTY(EditAnywhere)
FName LevelToLoad;

private:
// Overlap volume to trigger level streaming
UPROPERTY(VisibleAnywhere, BlueprintReadOnly,
meta = (AllowPrivateAccess = “true”))
UBoxComponent *OverlapVolume;
};

LevelStreamerActor.cpp

include “LevelStreamerActor.h”
include “Characters/MyCharacter.h”
include “Kismet/GameplayStatics.h”
include “CoreMinimal.h”

ALevelStreamerActor::ALevelStreamerActor() {
PrimaryActorTick.bCanEverTick = true;

OverlapVolume = CreateDefaultSubobject(TEXT(“OverlapVolume”));
RootComponent = OverlapVolume;

OverlapVolume->OnComponentBeginOverlap.AddUniqueDynamic(
this, &ALevelStreamerActor::OverlapBegins);

OverlapVolume->OnComponentEndOverlap.AddUniqueDynamic(
this, &ALevelStreamerActor::OverlapEnds);
}
void ALevelStreamerActor::BeginPlay() { Super::BeginPlay(); }

void ALevelStreamerActor::Tick(float DeltaTime) { Super::Tick(DeltaTime); }

void ALevelStreamerActor::OverlapBegins(
UPrimitiveComponent *OverlappedComponent, AActor *OtherActor,
UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep,
const FHitResult &SweepResult) {
ACharacter *MyCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
// comparison of distinct pointer types error unless casted
AActor *MyCharacterAsActor = Cast(MyCharacter);
if (OtherActor == MyCharacterAsActor && LevelToLoad != “”) {
FLatentActionInfo LatentInfo;
UGameplayStatics::LoadStreamLevel(this, LevelToLoad, true, true,
LatentInfo);
}
}

void ALevelStreamerActor::OverlapEnds(UPrimitiveComponent *OverlappedComponent,
AActor *OtherActor,
UPrimitiveComponent *OtherComp,
int32 OtherBodyIndex) {
ACharacter *MyCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
if (OtherActor == MyCharacter && LevelToLoad != “”) {
FLatentActionInfo LatentInfo;
UGameplayStatics::UnloadStreamLevel(this, LevelToLoad, LatentInfo, true);
}
}

Ive not tried handling level streaming with c++ yet just in editor, regarding the confusion on the level streaming volume, it needs to completely cover the level it’s assigned to. So if the level is 10,10,10, you’d want the streaming box to be at least that large or ideally slightly larger, also, the idea of level streaming isn’t to respawn a character in the level instance, but like you said in the first chunk, to “move” then. This streaming in a new level and streaming out the other. Based of your code, Wich I can’t say I understand completely but I do know some unreal c++, it seems like your spawning a new character every time an actor of the level streaming volume class begins play? Id think you’d want to keep it to just loading the new level

It might be your game mode auto-spawning in a character.

You could try bypassing the auto-spawn system for now as a test. Set the default pawn class in the game mode to None. Then try placing a character in your level manually and setting auto-possess on the character to player 0. See if the duplication occurs after that.