一、打AB包

1、编排打包资源的路径
2、使用脚本打包

打包之后会在ab包的目录生成一个与父目录相同的主清单文件。用来获取ab包的依赖关系。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using Net.Realmoon.Config;

public class ABBuilder
{
    [MenuItem("realmoon/Build Asset Bundle")]
    public static void BuildAsserBundles()
    {
        string dir = GameConfig.ABROOTPATH;
        if (!Directory.Exists(dir))
        {
            Directory.CreateDirectory(dir);
        }

        BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.StandaloneOSX);
    }
}

二、使用AB包

1、加载AB包的流程

  • 获取加载主清单文件:AB根路径/主文件名
  • 加载AB包的所有依赖包
  • 加载目标AB包:AB根路径[/子文件]/AB包文件(含拓展名)

2、加载AB包资源的流程

  • 加载AB包
  • 从AB包中加载资源

三、代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using Net.Realmoon.Singleton;
using Net.Realmoon.Mono;
using Net.Realmoon.IO.Files;
using Net.Realmoon.Config;
using System.IO;

namespace Net.Realmoon.IO.AB
{
    /// <summary>
    /// ab包工具类
    /// </summary>
    public class AssetBundleTools : SingletonBase<AssetBundleTools>
    {
        //主包资源
        private AssetBundle mainAssetBundle = null;
        private AssetBundleManifest mainManifest = null;
        //加载过的资源
        private Dictionary<string, AssetBundle> assetBundleMap = new Dictionary<string, AssetBundle>();

        /// <summary>
        /// 获取AB包的路径
        /// </summary>
        /// <returns></returns>
        public string GetABPath()
        {
            return Application.streamingAssetsPath + "/Android/";
        }

        #region 同步加载资源
        public void LoadAB(string abPath, string abName)
        {
            AssetBundle ab = null;

            //加载主包
            if (mainAssetBundle == null)
            {
                //加载主包
                mainAssetBundle = AssetBundle.LoadFromFile(GameConfig.ABMAINFASTPATH);
                //加载主包配置文件
                mainManifest = mainAssetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            }

            //获取依赖文件
            string[] dependencies = mainManifest.GetAllDependencies(abName);
            foreach (var dependency in dependencies)
            {
                if (!assetBundleMap.ContainsKey(dependency))
                {
                    ab = AssetBundle.LoadFromFile(Path.Join(abPath, dependency));
                    assetBundleMap.Add(dependency, ab);
                }
            }
            //加载资源包
            if (!assetBundleMap.ContainsKey(abName))
            {
                ab = AssetBundle.LoadFromFile(Path.Join(abPath, abName));
                assetBundleMap.Add(abName, ab);
            }
        }

        //加载指定资源
        public Object LoadAssetBundle(string abPath, string abName, string resName)
        {
            LoadAB(abPath, abName);

            //获取资源
            Object obj = assetBundleMap[abName].LoadAsset(resName);
            if (obj is GameObject)
            {
                return GameObject.Instantiate(obj);
            }
            return obj;

        }

        //同步加载指定类型的资源
        public Object LoadAssetBundle(string abPath, string abName, string resName, System.Type type)
        {
            LoadAB(abPath, abName);
            Object obj = assetBundleMap[abName].LoadAsset(resName, type);
            if (obj is GameObject)
            {
                return GameObject.Instantiate(obj);
            }
            return obj;
        }

        //同步加载指定类型的资源
        public T LoadAssetBundle<T>(string abPath, string abName, string resName) where T : Object
        {
            LoadAB(abPath, abName);
            T obj = assetBundleMap[abName].LoadAsset<T>(resName);
            if (obj is GameObject)
            {
                return GameObject.Instantiate(obj);
            }
            return obj;
        }

        /// <summary>
        /// 从ab包中读取文件
        /// </summary>
        /// <param name="abPath"></param>
        /// <param name="abName"></param>
        /// <param name="resName"></param>
        /// <returns></returns>
        public string LoadAssetBundleText(string abPath, string abName, string resName)
        {
            LoadAB(abPath, abName);
            TextAsset ta = assetBundleMap[abName].LoadAsset<TextAsset>(resName);
            if (ta == null)
            {
                return "";
            }
            else
            {
                return ta.text;
            }
        }
        #endregion

        #region 异步资源加载
        public void LoadAssetBundleAsync(string abPath, string abName, string resName, UnityAction<Object> callback)
        {
            MonoTools.Instance.StartCoroutine(ReallyLoadAssetBundleAsync(abPath, abName, resName, callback));
        }

        public IEnumerator ReallyLoadAssetBundleAsync(string abPath, string abName, string resName, UnityAction<Object> callback)
        {
            LoadAB(abPath, abName);
            AssetBundleRequest request = assetBundleMap[abName].LoadAssetAsync(resName);
            yield return request;
            Object obj = request.asset;

            if (obj is GameObject)
            {
                callback(GameObject.Instantiate(obj));
            }
            callback(obj);
        }

        public void LoadAssetBundleAsync(string abPath, string abName, string resName, System.Type type, UnityAction<Object> callback)
        {
            MonoTools.Instance.StartCoroutine(ReallyLoadAssetBundleAsync(abPath, abName, resName, type, callback));
        }

        public IEnumerator ReallyLoadAssetBundleAsync(string abPath, string abName, string resName, System.Type type, UnityAction<Object> callback)
        {
            LoadAB(abPath, abName);
            AssetBundleRequest request = assetBundleMap[abName].LoadAssetAsync(resName, type);
            yield return request;
            Object obj = request.asset;
            if (obj is GameObject)
            {
                callback(GameObject.Instantiate(obj));
            }
            callback(obj);
        }


        public void LoadAssetBundleAsync<T>(string abPath, string abName, string resName, UnityAction<T> callback) where T : Object
        {
            MonoTools.Instance.StartCoroutine(ReallyLoadAssetBundleAsync(abPath, abName, resName, callback));
        }

        public IEnumerator ReallyLoadAssetBundleAsync<T>(string abPath, string abName, string resName, UnityAction<T> callback) where T : Object
        {
            LoadAB(abPath, abName);
            AssetBundleRequest request = assetBundleMap[abName].LoadAssetAsync<T>(resName);
            yield return request;
            T obj = request.asset as T;
            if (obj is GameObject)
            {
                callback(GameObject.Instantiate(obj));
            }
            callback(obj);
        }

        #endregion


        #region 资源释放
        //释放单个ab包
        public void UnloadAssetBundle(string abName)
        {
            if (assetBundleMap.ContainsKey(abName))
            {
                assetBundleMap[abName].Unload(true);
                assetBundleMap.Remove(abName);
            }

        }
        //释放所有ab包
        public void Clear()
        {
            AssetBundle.UnloadAllAssetBundles(true);
            assetBundleMap.Clear();
            mainAssetBundle = null;
            mainManifest = null;
        }
        #endregion

        #region 判断
        /// <summary>
        /// ab文件是否存在
        /// </summary>
        /// <param name="abPath"></param>
        /// <param name="abName"></param>
        /// <returns></returns>
        public bool IsAbFileConains(string abPath, string abName)
        {
            if (abPath == null || abName == null || abPath.Equals("") || abName.Equals(""))
            {
                return false;
            }

            if (FileTools.Instance.IsFileExist(abPath + "/" + abName))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion
    }

}
最后修改日期: 2023年11月1日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。