UE4异步载入资源

转自:http://blog.ch-wind.com/ue4%E5%BC%82%E6%AD%A5%E8%BD%BD%E5%85%A5%E8%B5%84%E6%BA%90/

所有的“硬”指针指向的资源都会被UE4在启动时进行载入,为了防止某些情况下引发的巨大延迟,必要的时候我们需要使用异步资源载入系统。

本文参考:https://docs.unrealengine.com/latest/INT/Programming/Assets/AsyncLoading/index.html进行整理。同时也是研究引擎的记录。

对于异步载入有两个类很重要:FStringAssetReferences和TAssetPtr。

FStringAssetReferences是对资源(Asset)的“软”引用,这个结构在BP中使用起来就像是UObject指针一样。而TAssetPtr是对FStringAssetReferences的一个弱引用封装,同时规范所指向的类型,可以在需要的时候调用Get()来解析到具体的资源。

为了避免理解上的偏差,来实际测试一次是最快的。在代码中添加如下属性:

UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Test)
    FStringAssetReference tf;

UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Test)
    TAssetPtr<UTexture2D> ttp;

FstringAssetReference在可视化编辑器中显示如下,确实是可以当作UObject指针来使用:

TAssetPtr则显示如下:

大多数时候,异步载入一个单独的资源基本没什么意义,除非他真的很大。如果要批量异步载入资源的话,就需要用到Object Libraries。这个是Content brower用来进行资源筛选和显示的类,在游戏逻辑中使用也是可以的。

if (!ObjectLibrary)
{
       ObjectLibrary = UObjectLibrary::CreateLibrary(BaseClass, false, GIsEditor);
       ObjectLibrary->AddToRoot();
}
ObjectLibrary->LoadAssetDataFromPath(TEXT("/Game/PathWithAllObjectsOfSameType");
if (bFullyLoad)
{
       ObjectLibrary->LoadAssetsFromAssetData();
}

上面的代码对指定的目录创建了一个Library,并且资源进行了载入操作。第二个步骤并不是必须的:

TArray<FAssetData> AssetDatas;
ObjectLibrary->GetAssetDataList(AssetDatas);

for (int32 i = 0; i < AssetDatas.Num(); ++i)
{
       FAssetData& AssetData = AssetDatas[i];

       const FString* FoundTypeNameString = AssetData.TagsAndValues.Find(GET_MEMBER_NAME_CHECKED(UAssetObject,TypeName));

       if (FoundTypeNameString && FoundTypeNameString->Contains(TEXT("FooType")))
       {
              return AssetData;
       }
}

上面的代码在ObjectLibrary中进行筛选并将找到的第一个资源返回。

得到AssetData之后可以将其转换为FStringAssetReference,然后使用StreamableManager进行异步载入。

void UGameCheatManager::GrantItems()
{
       TArray<FStringAssetReference> ItemsToStream;
       FStreamableManager& Streamable = UGameGlobals::Get().StreamableManager;
       for(int32 i = 0; i < ItemList.Num(); ++i)
       {
              ItemsToStream.AddUnique(ItemList[i].ToStringReference());
       }
       Streamable.RequestAsyncLoad(ItemsToStream, FStreamableDelegate::CreateUObject(this, &UGameCheatManager::GrantItemsDeferred));
}

void UGameCheatManager::GrantItemsDeferred()
{
       for(int32 i = 0; i < ItemList.Num(); ++i)
       {
              UGameItemData* ItemData = ItemList[i].Get();
              if(ItemData)
              {
                     MyPC->GrantItem(ItemData);
              }
       }
}

StreamableManager可以对传递给他的StringReference所引用的资源全部进行载入操作。上面的例子中ItemList的定义为TArray< TAssetPtr<UGameItem> >。也就说针对一个弱引用的列表,获得所有的StringReference之后传递给StreamableManager进行一次性的异步载入。载入之后会调用回调函数以便及时进行处理。在回调函数之前,所有的引用都会被StreamableManager保留,防止其被垃圾回收。

如上,将StreamableManager和Object Libaries进行组合使用,即可实现异步的资源载入了。

时间: 2024-10-13 21:29:12

UE4异步载入资源的相关文章

Android异步载入全解析之大图处理

Android异步载入全解析之大图处理 异步载入中很重要的一部分就是对图像的处理,这也是我们前面用异步载入图像做示例的原因. 一方面是由于图像处理不好的话会很占内存,并且easyOOM,还有一方面,图像也比文字要大,载入比較慢.所以,在解说了怎样进行多线程.AsyncTask进行多线程载入后,先暂停下后面的学习.来对图像的异步处理进行一些优化工作. 为什么要对图像处理 为什么要对图像进行处理,这是一个很直接的问题.一张图像.无论你拿手机.相机.单反还是什么玩意拍出来,它就有一定的大小,可是在不同

Android异步载入全解析之使用多线程

异步载入之使用多线程 初次尝试 异步.异步,事实上说白了就是多任务处理.也就是多线程执行.多线程那就会有各种问题,我们一步步来看.首先.我们创建一个class--ImageLoaderWithoutCaches,从命名上.大家也看出来,这个类,我们实现的是不带缓存的图像载入,不多说,我们再创建一个方法--showImageByThread,通过多线程来载入图像: /** * Using Thread * @param imageView * @param url */ public void s

(源代码分析)Android-Universal-Image-Loader (图片异步载入缓存库)的使用配置

转载请注明出处:http://blog.csdn.net/u011733020 前言: 在Android开发中,对于图片的载入能够说是个老生常谈的问题了,图片载入是一个比較坑的地方.处理不好,会有各种奇怪的问题,比方 载入导致界面卡顿.程序crash. 因此 怎样高效的载入大量图片.以及怎样载入大分辨率的图片到内存.是我们想要开发一款优质app时不得不去面对与解决的问题. 通常开发中,我们仅仅有两种选择:① 使用开源框架  ②自己去实现处理图片的载入与缓存. 通常一開始让我们自己去写,我们会无从

Android异步载入全解析之开篇瞎扯淡

Android异步载入 概述 Android异步载入在Android中使用的很广泛,除了是由于避免在主线程中做网络操作.更是为了避免在显示时由于时间太长而造成ANR,添加显示的流畅性,特别是像ListView.GridView这种控件.假设getView的时间太长,就会造成很严重的卡顿,很影响性能. 本系列将展示在Android中怎样进行异步载入操作,并使用ListView来作为演示的对象. 怎样下载图像 下载自然是须要使用网络,使用网络就不能在主线程.在主线程就会爆炸.所以我们必须要在非主线程

Android异步载入全解析之IntentService

Android异步载入全解析之IntentService 搞什么IntentService 前面我们说了那么多,异步处理都使用钦定的AsyncTask.再不济也使用的Thread,那么这个IntentService是个什么鬼. 相对与前面我们提到的这两种异步载入的方式来说.IntentService有一个最大的特点.就是--IntentService不受大部分UI生命周期的影响.它为后台线程提供了一个更直接的操作方式.只是,IntentService的不足主要体如今下面几点: 不能够直接和UI做

UE4 异步资源加载

On this page: 概述 FStringAssetReferences 和TAssetPtr 资源注册表和对象库 StreamableManager(动态加载管理器)和异步加载 概述 虚幻引擎4中有几个新系统,使得可以更加轻松地异步加载资源数据,这些系统代替了虚幻引擎3中的免搜索内容包中存在的很多功能.这些新方法既可以在开发数据应用也可以在设备上的烘焙数据上进行应用,所以您不必保留两个根据需要加载数据的代码路径.有两种通用的方法可以供您根据需要来引用及加载数据. FStringAsset

async和await异步编程资源汇总

中文资料 使用 Async 和 Await 的异步编程 以上这篇文章是微软的,讲的很详细,还包括了大量的实验和实例代码,比如 演练:使用 Async 和 Await 访问 Web 如何:使用 Task.WhenAll 扩展异步演练 如何:使用 Async 和 Await 并行发起多个 Web 请求 取消一个异步任务或一组任务 在一段时间后取消异步任务 在完成一个异步任务后取消剩余任务 以及其他的资源链接,还有相应的英文版本,英文好的朋友可以直接看原版 除了微软的之外,Steve Cleary作为

android 请求网络异步载入

/** * 封装ProecssDialog对话框 * */ public class LoadDialog extends ProgressDialog { private String title = "进度对话框"; private String message = "载入数据中...."; public LoadDialog(Context context, int theme) { super(context, theme); } /** * 用默认的标题和

使用jquery+一般处理程序异步载入信息

需求:有时候.web界面对性能要求比較高.我们就不考虑使用asp.net控件.而是使用html标签+jquery+一般处理程序来进行异步处理. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvem91eXVqaWUxMTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > aspx代码: <asp:Repeater ID="rptR