跳到主要内容

预加载资源

预加载(Preloading) 是一种提前加载资源的技术手段。

游戏中的资源(模型、贴图、音频、动画、场景等)往往体积较大,倘若在使用时才进行加载,可能导致:

  • 帧率骤降:资源加载时可能阻塞主线程;
  • 物体闪现: 场景中的一些物件可能在用户画面中突然出现;
  • 界面停顿:在打开新场景或切换UI时停顿会导致用户体验下降;
  • 音频延迟:例如点击按钮后,音效需要先加载才可以播放,可能导致播放滞后;

此时,资源预加载可以有效解决这些问题。通过在游戏启动、关卡加载或场景过渡阶段提前加载关键资源,可显著改善用户体验,使游戏运行更平滑、更具连续性。

使用资源清单预加载资源

winS.Unity.ResourceManagement 允许您通过 资源清单 的形式来预加载资源。

您可以通过创建winS.Unity.ResourceManagement.ResourceManifestjump icon的实例来创建资源清单。

资源清单接受一系列资源条目winS.Unity.ResourceManagement.ResourceEntryjump icon,通过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();
}
}