UE4异步加载场景(1)

本文介绍了UE4中一种非流关卡的异步加载场景方法,通过获取蓝图依赖资源的函数接口,封装成工具,将场景依赖的资源路径存储到DataTable,便于异步加载。文章提供了一个小工具的下载,并预告了下篇将分享异步加载场景的代码,适用于UE4.23版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1
说UE4异步加载场景,首先大家都能想到的就是流关卡(Level Streaming),这也是一种比较常见的异步加载场景的方法,官方提供了比较详细的使用方法大家可以看官方文档。
我们这里不说流关卡(Level Streaming)这种方式,我们用异步加载场景依赖资源的方式来解决异步加载场景的问题。说到异步加载场景依赖资源包,其实官方提供了如何获得蓝图依赖资源的函数接口。我自己只要稍微封装一下做成小工具就可以了。
第一篇呢我们就主要介绍这个工具,我会把工具插件附在文章末尾供大家下载。代码量很少有兴趣的大家可以阅读一下。
这个工具的功能就是把场景依赖的所有资源路径存储到一张DataTable中,这样其实就相当于这个场景的依赖资源路径都有了。后面我们进行异步加载场景时候直接加载DataTable的资源路径即可。
后面一篇我会把我地异步加载场景代码贴给大家。(UE版本4.23)图片已经标注了按钮功能,就是导出当前场景的所有依赖资源,并且还提供了一个根据场景表格,一次行导出多场景的依赖资源,大家配置一下场景表格,点一下表格导出就是根据场景表格导出
图片已经标注了按钮功能,就是导出当前场景的所有依赖资源,并且还提供了一个根据场景表格,一次行导出多场景的依赖资源,大家配置一下场景表格,点一下表格导出就是根据场景表格导出.
我发现资源审核有点慢,因为插件本身代码很少我贴代码出来给大家,下面这个代码就是核心插件代码。

// Fill out your copyright notice in the Description page of Project Settings.


#include "ExpoortJsonSceneEditor.h"
#include "AssetRegistryModule.h"
#include "DesktopPlatform/Public/IDesktopPlatform.h"
#include "SlateApplication.h"
#include "DesktopPlatform/Public/DesktopPlatformModule.h"
#include "FileHelper.h"
#include "FileHelpers.h"
#include "DataConfig.h"
#include "Editor.h"

void UExpoortJsonSceneEditor::RecursiveGetDependencies(const FName& PackageName, TArray<FName>& AllDependencies, bool isFirst)
{
   
	if (!PackageName.IsNone())
	{
   
		FAssetRegistryModule& AssetRegistryModule = FModuleManager::Get().LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
		TArray<FName> Dependencies;
		AssetRegistryModule.Get().GetDependencies(PackageName, Dependencies);
		if (isFirst &&
			!AllDependencies.Contains(PackageName) &&
			AddToSourceMapCondition(PackageName.ToString()))
		{
   
			AllDependencies.Add(PackageName);
		}

		for (auto DependsIt = Dependencies.CreateConstIterator(); DependsIt; ++DependsIt)
		{
   
			if 
<think>嗯,用户问的是在Unreal Engine中如何实现异步加载。我需要先回想一下UE异步加载的常用方法。首先,可能想到的是使用AsyncLoad资产,比如UAssetManager或者FStreamableManager。然后,还有异步加载关卡的功能,比如使用LoadStreamLevel或者Level Streaming的蓝图节点。另外,可能还要提到异步加载纹理、静态网格等资源的具体方法,比如使用FStreamableHandle或者AsyncTask。 不过用户可能是一个刚开始学习UE的开发者,可能对异步加载的概念不太清楚,需要先解释一下为什么需要异步加载,比如避免主线程卡顿,提升用户体验。然后分步骤介绍不同的方法,比如资源加载和关卡加载的区别。可能需要提到使用PrimaryAssetId来标识资源,然后通过AsyncLoadPrimaryAsset来加载。另外,FStreamableManager的RequestAsyncLoad也是一个常用的方法,可以加载一组资源并在完成后回调。 在代码示例方面,用户可能需要看到具体的C++或者蓝图的例子。比如在C++中,如何声明FStreamableManager,如何绑定回调函数。在蓝图中,可能使用Delay节点或者Async Load Asset节点,但要注意蓝图的异步操作可能需要使用到事件分发器或者Latent Action。 还要注意资源管理的问题,比如加载后的资源需要正确释放,避免内存泄漏。可能需要提醒用户在使用完毕后手动Unload,或者使用引用计数。另外,异步加载过程中的错误处理也很重要,比如加载失败的情况需要处理,可以添加OnLoadFailed的回调。 可能用户的实际应用场景是在游戏运行时动态加载角色模型、场景元素或者大型地图,所以举例说明这些情况会更有帮助。比如在开放世界游戏中,当玩家接近某个区域时,异步加载该区域的关卡和资源,以保证流畅性。 需要确认UE的版本是否影响异步加载的实现方式,比如在UE4UE5中是否有差异。不过一般来说,FStreamableManager和AsyncLoadPrimaryAsset在两者中都是可用的。此外,还可以提到Unreal的异步加载系统底层可能使用了Pak文件加载,或者基于AsyncLoadingThread的机制,但用户可能不需要了解这么深入,除非有特别需求。 总结起来,回答的结构应该是先介绍异步加载的作用,然后分资源加载和关卡加载两部分,分别介绍实现方法,给出C++和蓝图的示例,最后提一下注意事项和最佳实践。这样用户能够有一个清晰的步骤去实现,同时了解潜在的问题和解决方案。</think>在虚幻引擎(Unreal Engine)中,异步加载的核心目标是避免主线程阻塞,提升运行效率。以下是分步实现方法: --- ### **一、异步加载资源(纹理、模型等)** #### **1. 使用 `FStreamableManager`** ```cpp // 头文件声明 #include "UObject/SoftObjectPath.h" #include "Engine/StreamableManager.h" // 代码实现 void UMyClass::LoadAssetAsync() { FStreamableManager& Streamable = UAssetManager::GetStreamableManager(); TArray<FSoftObjectPath> AssetsToLoad; AssetsToLoad.Add(FSoftObjectPath(TEXT("/Game/Textures/MyTexture.MyTexture"))); // 异步加载并绑定回调 Streamable.RequestAsyncLoad(AssetsToLoad, FStreamableDelegate::CreateUObject(this, &UMyClass::OnAssetsLoaded)); } void UMyClass::OnAssetsLoaded() { // 资源加载完成后的逻辑 UTexture2D* LoadedTexture = LoadObject<UTexture2D>(nullptr, TEXT("/Game/Textures/MyTexture.MyTexture")); } ``` #### **2. 蓝图实现** 1. 使用 **`Async Load Asset`** 节点 2. 连接 **`OnLoadCompleted`** 事件处理加载结果 --- ### **二、异步加载关卡** #### **1. C++ 实现** ```cpp void UMyClass::LoadLevelAsync() { FLatentActionInfo LatentInfo; LatentInfo.CallbackTarget = this; LatentInfo.ExecutionFunction = "OnLevelLoaded"; LatentInfo.Linkage = 0; UGameplayStatics::LoadStreamLevelBySoftObjectPtr(GetWorld(), LevelToLoad, true, true, LatentInfo); } void UMyClass::OnLevelLoaded() { // 关卡加载完成后的逻辑 } ``` #### **2. 蓝图实现** 1. 使用 **`Load Stream Level`** 节点 2. 勾选 **`Make Visible After Load`** 和 **`Should Block on Load`** 参数 --- ### **三、异步加载数据资产** ```cpp // 使用 Primary Asset 系统 void UMyClass::LoadPrimaryAssetAsync() { TArray<FPrimaryAssetId> AssetsToLoad; AssetsToLoad.Add(FPrimaryAssetId("MyAssetType", "MyAssetName")); UAssetManager::Get().LoadPrimaryAssets(AssetsToLoad, TArray<FName>(), FStreamableDelegate::CreateUObject(this, &UMyClass::OnPrimaryAssetLoaded)); } ``` --- ### **四、关键技术点** 1. **回调机制**:通过 `FStreamableDelegate` 或蓝图事件绑定后续逻辑 2. **资源引用**:保持对加载资源的强引用(如 `UPROPERTY()`),防止被GC回收 3. **进度跟踪**:通过 `GetAsyncLoadPercentage()` 监控加载进度 4. **错误处理**:检查加载结果有效性,处理加载失败情况 --- ### **五、最佳实践** - 对大型资源(如4K纹理)使用异步加载 - 在场景过渡时预加载下一场景资源 - 结合加载屏幕(Loading Screen)显示进度条 - 使用 `CancelLoading()` 支持取消操作 --- 通过结合C++底层控制和蓝图可视化编程,可以灵活实现不同复杂度的异步加载需求。实际开发中需根据性能分析和项目需求选择最合适的方案。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值