目录
有时可能会遇到关卡已经进去但依然会卡顿一段时间的情况,所以我们需要在进入关卡后,玩家可以操作关卡之前,对关卡内的资产和一些重要的资产进行加载,同时为了尽可能加载完全进行一些伪加载,加载界面效果如下:
一、创建自定义AssetManager类
在编辑器中创建一个c++类,选择AssetManager为父类,下面那个类就是我们已经创建好的类
然后在项目设置->引擎->一般设置->默认类->高级 中将资产管理器类改成我们刚才生成的c++类
此类是可以被静态获取的:
//.h中的声明
UFUNCTION(BlueprintPure,BlueprintCallable,Category="AssetLoader")
static UAstromutateAssetManager* GetAstromutateAssetManager();
//.cpp中实现
UAstromutateAssetManager* UAstromutateAssetManager::GetAstromutateAssetManager()
{
auto Temp{Cast<UAstromutateAssetManager>(GEngine->AssetManager)};
if(Temp)
{
return Temp;
}
UE_LOG(LogTemp,Error,TEXT("GetAssetManager failed"));
return NewObject<UAstromutateAssetManager>();
}
二、异步加载资产
首先,我们声明动态委托,用于在有资产加载完成后统计加载进度:
DECLARE_DYNAMIC_DELEGATE(FAssetLoaded);
然后是加载资产的函数,传入资产路径和触发的事件,因为事件是在UI蓝图里实现的,资产路径是纯净路径,也就是没有单引号,没有后缀点的路径
void UAstromutateAssetManager::LoadLevelAsset( FSoftObjectPath LevelName, FAssetLoaded AssetLoadedEvent)
{
//检查路径是否合法
if(!LevelName.IsValid())
{
UE_LOG(LogTemp,Error,TEXT("LoadLevel failed,invalid name:%s"),*LevelName.ToString())
}
UE_LOG(LogTemp,Warning,TEXT("LoadingLevel:%s"),*LevelName.ToString());
//虚幻提供的异步加载函数,具体原理尚待研究
LoadPackageAsync(CurrentLoadingPackage,FLoadPackageAsyncDelegate::CreateLambda([=](const FName&PackageName,UPackage* LoadedPackage,EAsyncLoadingResult::Type Result)
{
//加载成功
if(Result==EAsyncLoadingResult::Succeeded)
{
UE_LOG(LogTemp,Warning,TEXT("LoadLevelAsset successed"));
AssetLoadedEvent.ExecuteIfBound();
}
}),0,PKG_ContainsMap);
}
三、加载界面UI的实现
1.UI布局
作为变量的就是开始游戏的按钮和进度条:
2.在打开关卡前和进入关卡后创建UI并统计进度
首先将开始游戏按钮隐藏,然后我们从游戏实例中获取当前是新游戏还是在加载存档,然后如果要加载的存档的索引是-2,该UI就是打开关卡后的UI,是-1的话该UI是进入关卡前的UI且是新游戏,否则就是要加载的存档的索引。
对于进入关卡前的UI,我们先延迟一秒,做一个伪加载,然后开始异步加载所有要加载的资产,同时每加载好一个就令当前进度+1,全部加载好之后将进度推进到0.5,然后根据是否是新游戏,具体执行读档或者直接打开关卡,无论是哪个,打开关卡后都会再次创建一个新的该UI。
然后对于进入关卡后的UI,我们设置一个定时器每秒统计一下进度
下面是更新进度的函数,BP_EventManager是关卡中负责执行读档函数的Actor,在玩家pawn、HUD、Controller的BeginPlay执行完毕后,都会反馈给该Actor,这里我们每次进入这个函数只检查其中一个是否加载完成,也是为了延长加载时间做的伪加载,其中Controller加载好之后就可以先把游戏暂停了,因为我们游戏是有失败进度累计的,在最后检查完存档数据全部加载完成后或者是新游戏再继续游戏,同时显示开始游戏按钮,玩家可以点击按钮关闭UI进入关卡: