2024-12-06 Unity Addressables3——资源加载

发布于:2024-12-08 ⋅ 阅读:(147) ⋅ 点赞:(0)

  • Unity 版本:6000.0.26f1c1
  • Addressables 版本:2.3.1

1 引用加载

1.1 Addressables 的资源引用类

  • AssetReference:通用资源引用类,可加载任意类型资源。
  • AssetReferenceAtlasedSprite:图集资源引用类。
  • AssetReferenceGameObject:游戏对象资源引用类。
  • AssetReferenceSprite:精灵图片资源引用类。
  • AssetReferenceTexture:贴图资源引用类。
  • AssetReferenceT<>:指定类型引用类。

​ 通过申明不同类型引用类对象,可以在 Inspector 窗口中筛选关联的 Addressables 对象。

public class Lesson3 : MonoBehaviour
{
    public AssetReference              AssetReference;
    public AssetReferenceAtlasedSprite AssetReferenceAtlasedSprite;
    public AssetReferenceGameObject    AssetReferenceGameObject;
    public AssetReferenceSprite        AssetReferenceSprite;
    public AssetReferenceTexture       AssetReferenceTexture;

    public AssetReferenceT<AudioClip>                 AssetReferenceTAudioClip;
    public AssetReferenceT<RuntimeAnimatorController> AssetReferenceTRuntimeAnimatorController;
    public AssetReferenceT<TextAsset>                 AssetReferenceTTextAsset;
    public AssetReferenceT<Material>                  AssetReferenceTMaterialRed;
    public AssetReference                             AssetReferenceTScene;
}
image-20241206164715350

1.2 加载资源

注意:所有 Addressables 加载相关都使用异步加载。

需要引用命名空间:using UnityEngine.ResourceManagement.AsyncOperations;

public class Lesson3 : MonoBehaviour
{
    public AssetReference AssetReference;
    ...

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        // 1. 使用异步操作句柄
        AsyncOperationHandle<GameObject> handle = assetReference.LoadAssetAsync<GameObject>();
        handle.Completed += TestFun;
        
        // 2. 简化写法
        AssetReference.LoadAssetAsync<GameObject>().Completed += handle =>
        {
            // 判断是否加载成功
            // 建议使用传入参数
            if (handle.Status == AsyncOperationStatus.Succeeded)
            {
                var obj = Instantiate(handle.Result);
                obj.name = "Loaded GameObject";
            }
            
            // 不建议使用标识类创建
            // if(assetReference.IsDone)
            // {
            //    Instantiate(assetReference.Asset);
            // }
        };
    }

    private void TestFun(AsyncOperationHandle<GameObject> handle)
    {
        // 加载成功后,使用加载的资源嘛
        // 判断是否加载成功
        if(handle.Status == AsyncOperationStatus.Succeeded)
        {
            Instantiate(handle.Result);
        }
    }
}

1.3 加载场景

public class Lesson3 : MonoBehaviour
{
    public AssetReference AssetReferenceTScene; // 需要引用 Scene 资源
    ...

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        AssetReferenceTScene.LoadSceneAsync().Completed += (handle) =>
        {
           // 初始化场景的一些信息
           print("场景加载结束");
        };
    }
}

1.4 释放资源

        AssetReference.ReleaseAsset();

  1. 释放资源方法后,资源引用类中的资源会置空,但是 AsyncOperationHandle 类中的对象不为空。
  2. 释放资源不会影响场景中被实例化出来的对象,但是会影响使用的资源。
public class Lesson3 : MonoBehaviour
{
    public AssetReference AssetReference;
    ...

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        AssetReference.LoadAssetAsync<GameObject>().Completed += handle =>
        {
            if (handle.Status == AsyncOperationStatus.Succeeded)
            {
                var obj = Instantiate(handle.Result);
                obj.name = "Loaded GameObject";
                
                // 加载完成后,释放资源
                AssetReference.ReleaseAsset();
                    
                Debug.Log(handle.Result == null);        // false
                Debug.Log(AssetReference.Asset == null); // true
            }
        };
    }
}

2 Label 介绍

​ 引用加载必须在脚本中声明各种引用类来指定加载的资源,不够灵活,只适合做一些小项目。

​ 实际商业项目开发中,很多时候根据配置文件决定加载的资源,即动态加载。

​ 通过给定名称和标签,来加载指定资源。

image-20241206170645705

Label 作用举例:

  1. 游戏装备中有一顶帽子:Hat,拥有不同的品质,比如:红、绿、白、蓝。

    通过标签 Label 来区分,Label 分别是:Red、Green、White、Blue。

  2. 游戏中根据设备好坏选择不同质量的图片或者模型,比如:高清、标清、超清。

    但在不同标准下,这些模型的命名应该是相同的,Label 分别是:HD、SD、FHD。

  3. 游戏中逢年过节时更换模型和 UI 显示,比如:中秋节、春节、圣诞节。

    不同节日时角色或者 UI 等资源看起来是不同的,但资源的命名应该都遵循同样的规范。

    比如登录面板,在中秋节、春节、圣诞节时它的资源名都是登录面板,Label 分别可以是:MidAutumn、Spring、Christmas。

3 动态加载

  • 命名空间:

    UnityEngine.AddressableAssets

    UnityEngine.ResourceManagement.AsyncOperations

​ 以下是打包示例:

image-20241206172212626

3.1 加载单个资源

(1)通过资源名或标签名动态加载单个资源

​        public static AsyncOperationHandle<TObject> LoadAssetAsync<TObject>(object key);

注意:

  1. 如果存在同名或同标签的同类型资源,会自动加载第一个满足条件的对象。
  2. 如果存在同名或同标签的不同类型资源,可以根据泛型类型来决定加载哪一个。

​ 以加载标签为 “Red” 的 GameObject 资源为例:

public class Lesson5 : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        Addressables.LoadAssetAsync<GameObject>("Red").Completed += handle =>
        {
            if (handle.Status == AsyncOperationStatus.Succeeded)
            {
                Instantiate(handle.Result);
            }
        };
    }
}

​ 以加载名称为 “Red” 的 GameObject 资源为例:

public class Lesson5 : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        Addressables.LoadAssetAsync<GameObject>("Cube").Completed += handle =>
        {
            if (handle.Status == AsyncOperationStatus.Succeeded)
            {
                Instantiate(handle.Result);
            }
        };
    }
}

(2)动态加载场景

public static AsyncOperationHandle<SceneInstance> LoadSceneAsync(

​        object key,

        LoadSceneMode loadMode = LoadSceneMode.Single,

        bool activateOnLoad = true,

​        int priority = 100,

​        SceneReleaseMode releaseMode = SceneReleaseMode.ReleaseSceneWhenSceneUnloaded

);

  • key:场景名。
  • loadMode:加载模式。
    • LoadSceneMode.Single:单独加载,只保留新加载的场景;
    • LoadSceneMode.Additive:叠加加载,两个场景一起显示(不常用)。
  • activateOnLoad:场景加载是否激活。如果为 false,加载完成后不会直接切换,需要自己使用返回值中的 ActivateAsync 方法。
  • priority:场景加载的异步操作优先级。
  • releaseMode:释放模式。
    • SceneReleaseMode.ReleaseSceneWhenSceneUnloaded:卸载场景时释放;
    • SceneReleaseMode.OnlyReleaseSceneOnHandleRelease:手动释放。

​ 例如,加载 SampleScene 场景并手动激活:

public class Lesson5 : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        Addressables.LoadSceneAsync("SampleScene", LoadSceneMode.Single, false, 100).Completed += (obj) =>
        {
            // 手动激活场景
            obj.Result.ActivateAsync();
        };
    }
}

(3)释放资源

        public static void Release<TObject>(AsyncOperationHandle<TObject> handle)

​ 释放资源时,需要记录加载后的 Handle。

public class Lesson5 : MonoBehaviour
{
    public AsyncOperationHandle<GameObject> Handle;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        Handle = Addressables.LoadAssetAsync<GameObject>("Cube");

        Handle.Completed += operationHandle =>
        {
            if (operationHandle.Status == AsyncOperationStatus.Succeeded)
            {
                Instantiate(operationHandle.Result);

                // 加载完成后,释放资源
                Addressables.Release(Handle);
            }
        };
    }
}

注意:

​ 一定要保证资源使用完毕过后再释放资源。

​ 建议将 Play Mode Script 改为 “Use Existing Build” 测试,因为 “Use Asset Database” 模式下,不会真正地从 AB 包释放资源。

image-20241206173338294

3.2 加载多个资源

(1)重载一

public static AsyncOperationHandle<IList<TObject>> LoadAssetsAsync<TObject>(

        object key,

        Action<TObject> callback,

        bool releaseDependenciesOnFailure

);

  • key:资源名或标签名。
  • callback:每个加载资源结束后会调用的函数,会把加载到的资源传入该函数中。
  • releaseDependenciesOnFailure:为 true,当资源加载失败时自动将已加载的资源和依赖释放;为 false,需要自己手动来管理释放。
public class Lesson6 : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        var handle = Addressables.LoadAssetsAsync<GameObject>("Red", obj =>
        {
            // (1):应用于每个 GameObject,与 (2) 等价
            Debug.Log(obj.name);
        }, true);

        // (2):遍历 GameObject 列表,与 (1) 等价
        handle.Completed += (obj) =>
        {
            foreach (var o in obj.Result)
            {
                Debug.Log(o.name);
            }
        };
    }
}

(2)重载二

public static AsyncOperationHandle<IList<TObject>> LoadAssetsAsync<TObject>(

        IEnumerable keys,

        Action<TObject> callback,

        MergeMode mode,

        bool releaseDependenciesOnFailure

);

  • keys:想要加载资源的条件列表(资源名、Lable 名)。

  • callback:每个加载资源结束后会调用的函数,会把加载到的资源传入该函数中。

  • mode:可寻址的合并模式,用于合并请求结果的选项。

    如果键 “Cube”、“Red” 分别对应结果 [1, 2, 3]、[1, 3, 4](数字代表不同的资源):

    • MergeMode.None:不发生合并,将使用第一组结果 结果为 [1, 2, 3];
    • MergeMode.UseFirst:应用第一组结果,结果为 [1, 2, 3];
    • MergeMode.Union:合并所有结果,结果为 [1, 2, 3, 4];
    • MergeMode.Intersection:使用相交结果,结果为 [1, 3]。
  • releaseDependenciesOnFailure:为 true,当资源加载失败时自动将已加载的资源和依赖释放;为 false,需要自己手动来管理释放。

public class Lesson6 : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        Addressables.LoadAssetsAsync<Object>(
            new[] { "Cube", "Red" },
            obj => { Debug.Log(obj.name); }, // 打印结果:"Cube"
            Addressables.MergeMode.Intersection,
            true
        );
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到