在发起异步加载关卡的时候,需要传入一个FLatentActionInfo结构体,里面放入回调信息。包括必要的:

  • 回调执行对象(this)
  • 回调要执行的函数(OnSceneLoaded)
void UTest::LoadScene()
{
    FLatentActionInfo LatentInfo;
    LatentInfo.CallbackTarget = this;
    LatentInfo.ExecutionFunction = "OnSceneLoaded";
    LatentInfo.UUID = 1234;
    LatentInfo.Linkage = 1;
    // 两个布尔值参数分别代表:加载完成后是否马上显示出来、加载时是否阻塞
    UGameplayStatics::LoadStreamLevel(this, TEXT("/Game/Scene/TestSubLevel"), true, false, LatentInfo);
}

void UTest::OnSceneLoaded()
{
    UE_LOG(LogTemp, Log, TEXT("UTest::OnSceneLoaded()"))
}

接下来就是发起一个流式加载的行为了,这部分代码在UGameplayStatics::LoadStreamLevel()中。

void UGameplayStatics::LoadStreamLevel(const UObject* WorldContextObject, FName LevelName, bool bMakeVisibleAfterLoad, bool bShouldBlockOnLoad, FLatentActionInfo LatentInfo)
{
    if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull))
    {
        FLatentActionManager& LatentManager = World->GetLatentActionManager();
        if (LatentManager.FindExistingAction<FStreamLevelAction>(LatentInfo.CallbackTarget, LatentInfo.UUID) == nullptr)
        {
            FStreamLevelAction* NewAction = new FStreamLevelAction(true, LevelName, bMakeVisibleAfterLoad, bShouldBlockOnLoad, LatentInfo, World);
            LatentManager.AddNewAction(LatentInfo.CallbackTarget, LatentInfo.UUID, NewAction);
        }
    }
}

这里的代码其实很好懂了。

首先判断有没有存在这个行为,如果已经存在了就不再追加。

若不存在该行为,那么使用回调信息(使用结构体FLatentActionInfo中的信息)创建一个FStreamLevelAction行为。

FStreamLevelAction继承于FPendingLatentAction行为基类。在这一节先知道这个就好了,后面再详细解释。

UE4关卡流式加载与LatentAction - 知乎 (zhihu.com)