预加载资源
预加载(Preloading) 是一种提前加载资源的技术手段。
游戏中的资源(模型、贴图、音频、动画、场景等)往往体积较大,倘若在使用时才进行加载,可能导致:
- 帧率骤降:资源加载时可能阻塞主线程;
- 物体闪现: 场景中的一些物件可能在用户画面中突然出现;
- 界面停顿:在打开新场景或切换UI时停顿会导致用户体验下降;
- 音频延迟:例如点击按钮后,音效需要先加载才可以播放,可能导致播放滞后;
此时,资源预加载可以有效解决这些问题。通过在游戏启动、关卡加载或场景过渡阶段提前加载关键资源,可显著改善用户体验,使游戏运行更平滑、更具连续性。
使用资源清单预加载资源
winS.Unity.ResourceManagement 允许您通过 资源清单 的形式来预加载资源。
您可以通过创建winS.Unity.ResourceManagement.ResourceManifest
的实例来创建资源清单。
资源清单接受一系列资源条目winS.Unity.ResourceManagement.ResourceEntry
,通过ResourceManifest.Load方法,资源清单上的资源条目会被预加载,如下所示:
using System.Threading.Tasks;
using winS.Unity;
using winS.Unity.ResourceManagement;
public class Example_Preload
{
public async Task Preload()
{
ResourceManifest resourceManifest = new ResourceManifest();
resourceManifest.AddAssetEntry("Audio/Clip/Music/Battle/Level1");
resourceManifest.AddSingletonGameObjectEntry("Prefab/Player");
resourceManifest.AddMultitonGameObjectEntry("Prefab/Enemy/Skeleton", 5);
await resourceManifest.Load();//等待资源加载完毕
}
}
上述代码中,我们向资源清单中添加了以下资源:
- 一个地址为 "Audio/Clip/Music/Battle/Level1" 的资产;
- 一个地址为 "Prefab/Player" 的预设;
- 一个地址为 "Prefab/Enemy/Skeleton" 的多实例预设,其初始实例为5个;
获取预加载的资源
一旦资源被预加载完毕, 您就可以在任意地方通过Resource来快速获取资源:
using System.Threading.Tasks;
using UnityEngine;
using winS.Unity.ResourceManagement;
public class Example_Preload
{
public async Task Preload()
{
ResourceManifest resourceManifest = new ResourceManifest();
resourceManifest.AddAssetEntry("Audio/Clip/Music/Battle/Level1");
resourceManifest.AddSingletonGameObjectEntry("Prefab/Player");
resourceManifest.AddMultitonGameObjectEntry("Prefab/Enemy/Skeleton", 5);
await resourceManifest.Load();//等待资源加载完毕
AudioClip music = Resource.GetAsset<AudioClip>("Audio/Clip/Music/Battle/Level1");
GameObject player = Resource.GetSingletonGameObject("Prefab/Player");
GameObject skeleton = Resource.GetMultitonGameObject("Prefab/Enemy/Skeleton");
}
}
注意
若尝试获取未加载的资源,Resource 将返回 null 并发出错误消息。
更佳的做法
事实上,虽然以上代码可以正确使用,但我们更推荐使用 运行时资源表示,这将使代码有更佳的可维护性和可读性:
using System.Threading.Tasks;
using UnityEngine;
using winS.Unity.ResourceManagement;
public class Example_Preload2
{
public static readonly PrefabResource playerResource = new PrefabResource("Prefab/Player");
public static readonly PrefabsResource skeletonResource = new PrefabsResource("Prefab/Enemy/Skeleton");
public static readonly AudioClipResource musicResource = new AudioClipResource("Audio/Clip/Music/Battle/Level1");
public async Task Preload()
{
ResourceManifest resourceManifest = new ResourceManifest();
resourceManifest.Add(musicResource.GetResourceEntry());
resourceManifest.Add(playerResource.GetResourceEntry());
resourceManifest.Add(skeletonResource.GetResourceEntry(5));
await resourceManifest.Load();;
AudioClip music = musicResource.Get();
GameObject player = playerResource.Get();
GameObject skeleton = skeletonResource.Get();
}
}
释放资源
您可以通过调用ResourceManifest.Unload方法来释放对应的资源清单中记载的资源条目:
using System.Threading.Tasks;
using winS.Unity;
using winS.Unity.ResourceManagement;
public class Example_Unload
{
public static readonly PrefabResource player = new PrefabResource("Prefab/Player");
public static readonly PrefabsResource skeleton = new PrefabsResource("Prefab/Enemy/Skeleton");
public static readonly AudioClipResource music = new AudioClipResource("Audio/Clip/Music/Battle/Level1");
private readonly ResourceManifest resourceManifest = new ResourceManifest();
public async Task Preload()
{
resourceManifest.Add(music.GetResourceEntry());
resourceManifest.Add(player.GetResourceEntry());
resourceManifest.Add(skeleton.GetResourceEntry(5));
await resourceManifest.Load();;
}
public void Release()
{
resourceManifest.Unload();
}
}