虚幻引擎(UE4)实现加载等待页面Loading Screen设计(进度条异步加载)附工程源码
前言
在使用虚幻引擎设计产品中会经常使用切换地图,你是否也遇到启动软件会黑屏半天,或是切换地图黑屏一下?客户总是说体验不好!是否有办法解决呢?
首先需要了解为什么会黑屏一下,其实非常简单!因为计算机在启动软件后需要加载磁盘资产,加载过程是需要时间消耗的,但是有时候需要加载的资产又多,然后磁盘读取效率又低,所以导致等待时间过长。在加载的时候,软件窗口是空闲的,但是又没有其他渲染任务,所以就黑屏了。
所以大多数软件会设计Loading页面。Loading页面其实就是先加载小资产(数量少,速度快),然后让窗体渲染等待页面,对于使用者来说能看到软件反馈体验就会好很多。像一般软件启动显示Logo,广告,切换地图显示提示信息。
在虚幻引擎中实现加载页面大致有两种
- 纯粹的等待页面,例如绝地求生,添加等待图标,一直转圈等待
- 加载进度条等待页面,有进度条可以直观看到加载进度情况
两者区别是,第一种不知道要等待多久,因为并不知道执行后台任务的进度。第二种可以知道执行后台的任务进度,进度完成则加载完成。
第一种我们可以在社区的wiki找到实施方案(需要通过c++来实现)传送门。
本篇我们主要讲解第二种实施方案。
说明
第一二种方案其实都是一样的,都是需要借助后台加载资产,而不阻碍前台的逻辑执行,只是第二种多了加载进度的信息
整个过程我们需要借助两个函数(全局函数)
- LoadPackageAsync:完成后台的异步加载
- GetAsyncLoadPercentage:获取加载过程中的完成进度(值0-100)
在源码中有清晰的注释,说明函数的设计意图
建议
一般如果需要做过地图进度条,建议先将当前的关卡释放掉,以防内存占用过大被系统杀掉。所以更常规的做法一般是先切换到一个小关卡(openlevel即可),官方在实施无缝切换时也是使用此方案。
你可以先创建一个小关卡,在小关卡中启用异步后台加载,加载完成后再openlevel目标关卡(由于关卡资源已经加载过了,所以打开地图就无需等待)
实施
1、启动异步加载地图(放到任何执行一次逻辑中,不要多次执行),参照代码如下:
//MapPath是地图包名称,第二个参数为设定匿名函数,用来获取加载结果,你也可以自行设计绑定回调函数
LoadPackageAsync(MapPath.GetLongPackageName(), FLoadPackageAsyncDelegate::CreateLambda([this]( const FName& /*PackageName*/, UPackage* /*LoadedPackage*/, EAsyncLoadingResult::Type Result/*Result*/)
{
if (Result == EAsyncLoadingResult::Succeeded)
{
//可执行通知进行地图切换,即openlevel
}
}));
此代码段,可以编写在启动切换地图的执行逻辑中,执行一次即可。
地图包路径:右键地图资产,复制引用,将获取到引用路径,去掉额外信息参照如下:
复制结果:World’/Game/Environment_Set/Maps/Environment_Set_Map.Environment_Set_Map’
包名称:/Game/Environment_Set/Maps/Environment_Set_Map
通知代理:通知代理可以设置匿名函数,也可以绑定到成员函数,具体可以参照虚幻单播设计。主要是通知加载结果。
匿名函数中注意参数捕获传入捕获方式。否则无法完成外部通知。
2、获取资产加载进度。
//参考代码,注意返回值范围0-100,-1代表未发现加载包
float ALoadActor::GetLoadPercent()
{
//参数传入加载地图的包名称,注意参数类型是FName
return GetAsyncLoadPercentage(FName(MapPath.GetLongPackageName()));
}
注意,获取进度应该是需要轮询的,否则获取一次是无法知道过程的,毕竟加载是个时间流失过程。
最后
整个过程其实还是需要设计一下才可以,上面给到的是核心函数。
为了方便大家理解,我写了个插件,你可以插件工程来修改你的项目。
插件使用需要到项目配置中完成两项内容配置(启用插件才能看到配置项)。
测试地图:Main
链接:传送门
提取码:63yl
虚幻引擎:4.27.2
项目升级到5.1后打包就出问题了,找不到ISettingsSection.h和ISettingsModule.h,developer模块下打包不可用?
建议可以考虑去掉编辑器设置部分代码,这部分是为了测试添加的~直接使用业务代码即可解决问题~
老师,我这边在UE5 UE4都重新试着将关键代码写入到了GameInstance里面,编辑器运行没问题。但打包后加载界面没办法正常更新进度。最后写成多线程都没有解决。都是编辑器模式下正常打包不正常。
这部分稍后我测试下,抱歉网站一直没有更新~后面我邮件发你结果~
感谢老师,可以的话您直接更新到网站上,我经常过来学习。我邮箱注册的网站太多了都是官方信件,一天可能要好几十个邮件
可以关注下 Pome文章后续更新双网站同步~
新的工程我已经做了修改,存在一些BUG,由于使用编辑器设置,打包后设置数据无法随包发出。导致过度场景和UI无效,我已经修改了项目,可以看这里!新地址
OK 哈哈今天刚好都在
我自己之前只是将过渡关卡声明到GameInstance进行配置了,UI没有用C++的,只是将加载进度传递出去。打包一直都是场景可以正常打开,数据没办法正常加载。后来各种测试发现打包后和编辑器加载HUD等等这些的顺序都不一样,控制器中存储的ActorHUD去拿,打包和编辑器结果都不一样,编辑器功能正常打包不正常,干脆直接GetAllActorofClass了,刚刚看了一下过渡关卡直接配置GameInstance也拿不到真正的哪一个必须运行时给一个(本质还是打包后设置数据无法随包发出),这下填上了一个大坑。
你这个只是解决了从磁盘加载到内存中的异步,如果玩家一开始就已经把地图的包加载到内存了。卡顿的地方是在openlevel阶段,生成地图上的各种东西卡顿。
你说的问题和我在讲述的问题不是同一个问题