Unity可寻址系统提供了一个统一的资源管理接口,它允许我们通过地址来获取到任意类型的资源(如场景、贴图、音频等)。在使用Unity可寻址系统之前,我们需要对游戏资源进行打包,并生成相应的AssetBundle文件。具体打包的过程可以参考Unity官方文档。
可寻址资源的加载流程通常如下所示:
- 在Unity Editor中创建一个Addressable Asset,为其分配一个唯一的地址。
- 在打包时将这些已经分配好地址的资源打包成AssetBundle文件。
- 在游戏运行时通过地址来加载相应的AssetBundle文件。
- 加载AssetBundle文件后通过地址来获取相应的资源。
Unity可寻址系统的实现原理主要是通过以下三个类来实现:
- AddressableAssetSettings:可寻址系统的设置类,通过该类可以进行可寻址系统的配置和管理。
- AsyncOperationHandle:异步的操作句柄类,用于异步加载和释放可寻址资源。
- Addressables:可寻址系统的静态类,用于通过地址来获取相应的资源。
分标签加载可寻址资源
对于大型游戏而言,打包出的AssetBundle文件往往会非常庞大,这会导致加载资源时出现卡顿或者等待时间较长的情况。这时我们可以采取分标签加载的方式来优化资源的加载速度。分标签加载是将不同类型的资源打包到不同的AssetBundle文件中,并为其打上不同的标记。例如我们可以将场景、贴图、音频等不同的资源放在不同的AssetBundle文件中,并为其分别打上Scene、Texture、Audio等标记。这样当我们需要加载某一类型的资源时,只需要加载对应标记的AssetBundle文件即可。
下面我们演示如何使用分标签加载来优化可寻址资源的加载速度。
-
在Unity Editor中创建一个Addressable Asset并为其添加标记(Tag)。
-
编写代码来加载对应标记的AssetBundles,如下所示:
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class LoadAssetByTag : MonoBehaviour
{
public string tag = "MyTag"; // 需要加载的标记名称
// 加载对应标记的所有AssetBundle
public void LoadAssetsByTag()
{
AsyncOperationHandle<IList<string>> opHandle = Addressables.LoadResourceLocationsAsync(tag);
opHandle.Completed += OnComplete;
}
// 加载完成后回调
private void OnComplete(AsyncOperationHandle<IList<string>> obj)
{
if (obj.Status == AsyncOperationStatus.Succeeded)
{
foreach (var location in obj.Result)
{
Addressables.LoadAssetAsync<GameObject>(location).Completed += OnLoadAssetComplete;
}
}
}
// 加载单个AssetBundle中的资源完成后回调
private void OnLoadAssetComplete(AsyncOperationHandle<GameObject> obj)
{
if (obj.Status == AsyncOperationStatus.Succeeded)
{
Debug.Log("Load Asset Successfully: " + obj.Result.name);
}
}
}
以上代码会异步加载所有打上指定标记的AssetBundle,并在加载完成后输出每个AssetBundle中所包含的资源的名称。
代码加载可寻址资源
除了使用分标签加载可寻址资源外,我们还可以通过代码加载可寻址资源。这种方式适用于需要在游戏运行时动态加载资源的情况。下面我们演示如何使用代码加载可寻址资源。
-
在Unity Editor中创建一个Addressable Asset并为其分配一个唯一的地址。
-
编写代码来加载指定地址的资源,如下所示:
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class LoadAssetByAddress : MonoBehaviour
{
public string address; // 需要加载的地址
// 加载指定地址的AssetBundle
public void LoadAssetsByAddress()
{
AsyncOperationHandle<GameObject> opHandle = Addressables.LoadAssetAsync<GameObject>(address);
opHandle.Completed += OnComplete;
}
// 加载完成后回调
private void OnComplete(AsyncOperationHandle<GameObject> obj)
{
if (obj.Status == AsyncOperationStatus.Succeeded)
{
Instantiate(obj.Result); // 实例化已加载的GameObject
}
}
}
以上代码会异步加载指定地址的AssetBundle,并在加载完成后实例化其中包含的GameObject。
同时,在代码加载可寻址资源时,我们也可以使用LoadResourceLocationsAsync方法来获取所有打上指定标记的AssetBundle的地址列表,并根据需要来加载对应的资源。
// 获取指定标记的所有AssetBundle的地址列表
AsyncOperationHandle<IList<string>> opHandle = Addressables.LoadResourceLocationsAsync("MyTag");
opHandle.Completed += OnComplete;
// 加载所有地址列表中的资源
private void OnComplete(AsyncOperationHandle<IList<string>> obj)
{
if (obj.Status == AsyncOperationStatus.Succeeded)
{
foreach (var location in obj.Result)
{
Addressables.LoadAssetAsync<GameObject>(location).Completed += OnLoadAssetComplete;
}
}
}
总结
在本篇技术博客中,我们介绍了Unity可寻址系统的概念和实现原理,并演示了如何通过分标签加载和代码加载可寻址资源。使用Unity可寻址系统可以有效地管理游戏资源,并提高资源加载速度,使得游戏体验更加流畅。