前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unreal 01 - LoadMap

Unreal 01 - LoadMap

作者头像
Reck Zhang
发布2021-08-11 11:03:06
1.2K0
发布2021-08-11 11:03:06
举报
文章被收录于专栏:Reck Zhang

LoadMap

跟踪分析

  1. TRACE_LOADTIME_REQUEST_GROUP_SCOPE LoadTime
    1. LLM_SCOPE 低级内存跟踪器 | Unreal Engine Documentation
    2. NETWORK_PROFILER 网络分析器(Network Profiler) | Unreal Engine Documentation
    3. MALLOC_PROFILER

卸载资源

检查level streaming isn’t frozen

FCoreUObjectDelegates::PreLoadMap.Broadcast(URL.Map); 回调事件通知

注册析构函数PostLoadMap().

取消等待中的纹理流送请求UTexture2D::CancelPendingTextureStreaming(); 纹理流送概述 | Unreal Engine Documentation

卸载packageUEngine::CleanupPackagesToFullyLoad | Unreal Engine Documentation

代码语言:javascript
复制
if (WorldContext.World() && WorldContext.World()->PersistentLevel)
    {
        CleanupPackagesToFullyLoad(WorldContext, FULLYLOAD_Map, WorldContext.World()->PersistentLevel->GetOutermost()->GetName());
    }
CleanupPackagesToFullyLoad(WorldContext, FULLYLOAD_Game_PreLoadClass, TEXT(""));
CleanupPackagesToFullyLoad(WorldContext, FULLYLOAD_Game_PostLoadClass, TEXT(""));
CleanupPackagesToFullyLoad(WorldContext, FULLYLOAD_Mutator, TEXT(""));

强制同步阻塞处理异步加载, 确保没有异步加载还在进行FlushAsyncLoading();

取消所有等待中的地图异步更改CancelPendingMapChange(WorldContext);, 需要保证FlushAsyncLoading();在这之前执行

卸载当前world

关闭网络ShutdownWorldNetDriver(WorldContext.World());

同步阻塞处理level streamingFlushLevelStreaming, UWorld::FlushLevelStreaming | Unreal Engine Documentation

向所有level广播卸载事件FWorldDelegates::LevelRemovedFromWorld.Broadcast(nullptr, WorldContext.World());

将玩家与玩家控制器断开

代码语言:javascript
复制
WorldContext.World()->DestroyActor(Player->PlayerController->GetPawn(), true);
WorldContext.World()->DestroyActor(Player->PlayerController, true);
Player->PlayerController = nullptr;

清除玩家的view state, 防止world不能彻底cleanPlayer->CleanupViewState(); ULocalPlayer::CleanupViewState | Unreal Engine Documentation

销毁world中的ActorActorIt->RouteEndPlay(EEndPlayReason::LevelTransition);

执行CleanupWorld, WorldContext.World()->CleanupWorld();, 需在销毁pawns/playercontrollers后, 防止生成新的事物(如丢掉的武器)

将world从root set移除WorldContext.World()->RemoveFromRoot();

标记object删除CastChecked<UWorld>(Level->GetOuter())->MarkObjectsPendingKill();

标记level删除CastChecked<UWorld>(LevelStreaming->GetLoadedLevel()->GetOuter())->MarkObjectsPendingKill();

移除audioAudioDevice->Flush(WorldContext.World());

设置当前world为空WorldContext.SetCurrentWorld(nullptr);

同步阻塞进行全量GC TrimMemory();.

移除强制驻留的资源IStreamingManager::Get().CancelForcedResources();

检查world是否清理完毕VerifyLoadMapWorldCleanup();

加载资源

调用注册函数预加载资源CurrentWorld->GetGameInstance()->PreloadContentForURL(PendingTravelURL);

检查如果是PIE instance, 就修改PIERemapPrefix来加载这份world拷贝, 而不是直接加载PIE world.

代码语言:javascript
复制
NewWorld = UWorld::DuplicateWorldForPIE(SourceWorldPackage, nullptr);
NewWorld->StreamingLevelsPrefix = UWorld::BuildPIEPackagePrefix(WorldContext.PIEInstance);

如果是minimal net rpc world则创建UGameInstance::CreateMinimalNetRPCWorld(*URL.Map, WorldPackage, NewWorld);

常规地图加载

设置world typeUWorld::WorldTypePreLoadMap.FindOrAdd( URLMapFName ) = WorldContext.WorldType; WorldTypePreLoadMap | Unreal Engine Documentation

检查level是否已经在内存中WorldPackage = FindPackage(nullptr, *URL.Map);

如果level不在地图中, 则从磁盘进行加载WorldPackage = LoadPackage(nullptr, *URL.Map, (WorldContext.WorldType == EWorldType::PIE ? LOAD_PackageForPIE : LOAD_None));

PostLoad执行完毕后, 清理world type list.UWorld::WorldTypePreLoadMap.Remove( URLMapFName );

拿到加载完的worldNewWorld = UWorld::FindWorldInPackage(WorldPackage);

persistent level初始化NewWorld->PersistentLevel->HandleLegacyMapBuildData();

如果是world type是PIE, 尝试复制一份PIE worldNewWorld = CreatePIEWorldByDuplication(WorldContext, NewWorld, URL.Map);. NewWorld = CreatePIEWorldByLoadingFromPackage(WorldContext, URL.Map, WorldPackage);

设置world的context

代码语言:javascript
复制
NewWorld->SetGameInstance(WorldContext.OwningGameInstance);
GWorld = NewWorld;
WorldContext.SetCurrentWorld(NewWorld);
WorldContext.World()->WorldType = WorldContext.WorldType;

如果不是PIE, 将world加入root节点WorldContext.World()->AddToRoot();, 并进行world初始化WorldContext.World()->InitWorld();

将PendingNetGame中的NetDriver对象赋值给新的world的NetDriverMovePendingLevel(WorldContext);

设置game modeWorldContext.World()->SetGameMode(URL); Game Mode 和 Game State | Unreal Engine Documentation

audio device 初始化AudioDevice->SetDefaultBaseSoundMix(WorldContext.World()->GetWorldSettings()->DefaultBaseSoundMix);

监听客户端WorldContext.World()->Listen(URL)

处理异步完成的shader map, 并将其分配到对应的材质上GShaderCompilingManager->ProcessAsyncResults(false, true);

加载需要fully load的packageLoadPackagesFully(WorldContext.World(), FULLYLOAD_Map, WorldContext.World()->PersistentLevel->GetOutermost()->GetName());

确保”always loaded”子关卡已经全部加载完毕WorldContext.World()->FlushLevelStreaming(EFlushLevelStreamingType::Visibility);

在source level 完成创建后复制动态levelWorldContext.World()->DuplicateRequestedLevels(FName(*URL.Map));

初始化AI systemWorldContext.World()->CreateAISystem();

初始化level中的gameplayWorldContext.World()->InitializeActorsForPlay(URL, true, &Context);

初始化navigation systemFNavigationSystem::AddNavigationSystemToWorld(*WorldContext.World(), FNavigationSystemRunMode::GameMode);

为所有的local players创建player actor(*It)->SpawnPlayActor(URL.ToString(1),Error2,WorldContext.World())

通知stream manager开始texture streamingIStreamingManager::Get().NotifyLevelChange();

XRsystem初始化GEngine->XRSystem->OnBeginPlay(WorldContext); XRSystem | Unreal Engine Documentation

开始game playWorldContext.World()->BeginPlay();

发送回调信息PostLoadMapCaller.Broadcast(WorldContext.World());

更新streamRedrawViewports(false);

从streaming manager中移除所有streaming views IStreamingManager::Get().RemoveStreamingViews( RemoveStreamingViews_All );

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-02-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • LoadMap
    • 跟踪分析
      • 卸载资源
        • 加载资源
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档