我们想在此处的露台关卡中开始流送,这样在玩家转过拐角并开始靠近露台时,流送中的关卡 就会加载好并可见。

作为设置的一部分,我们有两个关卡:SunTemple_Persistent 和 SunTemple_Streaming 。我们的 玩家出生点(Player Start) 位于 SunTemple_Persistent 中,我们的玩家在游戏中 由 角色 表示。
-
在 内容浏览器(Content Browser) 中打开 SunTemple_Persistent 。
-
将 玩家出生点(Player Start) 移至模板的最开头。
-
点击 窗口(Windows),然后选择 关卡(Levels) 。
-
点击 关卡(Levels) 下拉菜单,然后选择 添加现有...(Add Existing...) 以添加新的子关卡。
-
选择 SunTemple_Streaming 以添加 打开关卡(Open Level) 对话框,然后点击 打开(Open) 。
-
右键点击 持久关卡(Persistent Level) ,并从下拉菜单选择 设为当前(Make Current) 。
使用C++在关卡中流送
-
打开 内容浏览器(Content Browser) 并创建新 C++类 。此类将基于 Actor ,因此选择 Actor 并点击 下一步(Next) 。
-
将新 C++类 命名为"LevelStreamerActor",然后点击 创建类(Create Class) 。该新类将在Visual Studio或XCode中打开。
对于这种情况,我们需要在 角色 与LevelStreamerActor中称为OverlapVolume的BoxComponent重叠时立即流送第二个关卡。
-
在
LevelStreamerActor.h
中,声明一个具有VisibleAnywhere、BlueprintReadOnly属性且有AllowPrivateAccess meta标记的OverlapVolume。private: // 重叠体积以触发关卡流送 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) UBoxComponent* OverlapVolume;
-
在
LevelStreamerActor.cpp
的LevelStreamerActor构造函数中,创建OverlapVolume并将其设为RootComponent。OverlapVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("OverlapVolume")); RootComponent = OverlapVolume;
-
回到
LevelStreamerActor.h
中,声明一个受保护OverlapBegins函数,它将绑定到BoxComponent的OnComponentBeginOverlap函数。此绑定意味着, OverlapBegins必须标记有UFUNCTION宏,并且必须拥有与OnComponentBeginOverlap相同的签名。protected: UFUNCTION() void OverlapBegins(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
-
同样在
LevelStreamerActor.h
中,创建一个EditAnywhere且名为LevelToLoad的受保护FName变量。这样一来,你就可以逐实例更改LevelToLoad。UPROPERTY(EditAnywhere) FName LevelToLoad;
-
我们将使用GameplayStatics库中的一些函数,因此请将其包含在
LevelStreamerActor.cpp
顶部。#include "Kismet/GameplayStatics.h"
-
现在你已准备好创建OverlapBegins功能。在
LevelStreamerActor.cpp
中,开始定义该函数。你可以使用GameplayStatics函数GetPlayerCharacter
获取索引0处的角色。void ALevelStreamerActor::OverlapBegins(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult) { ACharacter* MyCharacter = UGameplayStatics::GetPlayerCharacter(this, 0); }
-
获取MyCharacter后,针对与BoxComponent重叠的OtherActor检查它。此外,验证LevelToLoad是否不为空,然后调用LoadStreamLevel。
if (OtherActor == MyCharacter && LevelToLoad != "") { FLatentActionInfo LatentInfo; UGameplayStatics::LoadStreamLevel(this, LevelToLoad, true, true, LatentInfo); }
-
在LevelStreamerActor构造函数中,将OverlapBegins绑定到BoxComponent的OnComponentBeginOverlap。
OverlapVolume->OnComponentBeginOverlap.AddUniqueDynamic(this, &ALevelStreamerActor::OverlapBegins);
你的最终
LevelStreamerActor.h
应当如下所示:#pragma once #include "GameFramework/Actor.h" #include "LevelStreamerActor.generated.h" UCLASS() class LEVELS_API ALevelStreamerActor : public AActor { GENERATED_BODY() public: // 为此Actor的属性设置默认值 ALevelStreamerActor(); // 每一帧都调用 virtual void Tick( float DeltaSeconds ) override; protected: // 当游戏开始或生成时调用 virtual void BeginPlay() override; UFUNCTION() void OverlapBegins(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult); UPROPERTY(EditAnywhere) FName LevelToLoad; private: // 重叠体积以触发关卡流送 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) UBoxComponent* OverlapVolume; };
你的最终
LevelStreamerActor.cpp
应当如下所示:#include "Levels.h" #include "Kismet/GameplayStatics.h" #include "LevelStreamerActor.h" // 设置默认值 ALevelStreamerActor::ALevelStreamerActor() { // 将此Actor设置为每帧调用更新函数()。 如果不需要此特性,可以关闭以提升性能。 PrimaryActorTick.bCanEverTick = true; OverlapVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("OverlapVolume")); RootComponent = OverlapVolume; OverlapVolume->OnComponentBeginOverlap.AddUniqueDynamic(this, &ALevelStreamerActor::OverlapBegins); } // 当游戏开始或生成时调用 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); if (OtherActor == MyCharacter && LevelToLoad != "") { FLatentActionInfo LatentInfo; UGameplayStatics::LoadStreamLevel(this, LevelToLoad, true, true, LatentInfo); } }
-
编译你的代码,然后切换回编辑器。
-
将 LevelStreamer Actor放入关卡中,然后调整位置并缩放,直至它包含你希望 角色 位于其中才能开始流送的持久世界的一部分, 以及流送中的关卡将位于的整个可行走体积。
-
输入 *SunTemple_Streaming 作为 要流送的关卡** 。
-
使用在编辑器中运行(Play in Editor)来测试流送中的关卡。
使用C++卸载关卡
要在 角色 离开BoxComponent时卸载关卡,你需要创建 OverlapEnds
函数来调用 UGameplayStatics::UnloadStreamLevel
并将函数绑定到 OnComponentEndOverlap
。将以下代码片段添加到
你的LevelStreamerActor:
在LevelStreamerActor.h中:
UFUNCTION()
void OverlapEnds(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
在LevelStreamerActor.cpp中:
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);
}
}
在构造函数中:
OverlapVolume->OnComponentEndOverlap.AddUniqueDynamic(this, &ALevelStreamerActor::OverlapEnds);