# AssetBundle 创建与加载

  • AssetBundle 只能用代码创建和加载
  • 在创建前需要先为资源分配资源包,如图:img

# AssetBundle 的创建

  • 区分平台(Windows、OSX、Linux 等)
  • 区分创建方式(是否压缩、压缩方式等)
using System.IO;
using UnityEditor;
namespace Common
{
    /// <summary>
    /// CreateAssetBundles
    /// </summary>
    public class CreateAssetBundles
    {
        //[MenuItem("Assets/Build AssetBundles")]
        [MenuItem("Build/Build AssetBundles")]
        private static void BuildAllAssetBundles()
        {
            string assetBundleDirectory = "Assets/StreamingAssets/AssetBundles";
            BuildAssetBundleOptions assetBundleOptions;
            BuildTarget targetPlatform;
#if UNITY_EDITOR
            assetBundleOptions = BuildAssetBundleOptions.UncompressedAssetBundle;
            targetPlatform = BuildTarget.StandaloneWindows64;
#elif UNITY_STANDALONE_WIN //Windows 独立平台应用程序
            assetBundleOptions = BuildAssetBundleOptions.UncompressedAssetBundle;
            targetPlatform = BuildTarget.StandaloneWindows64;
#elif UNITY_STANDALONE_OSX //Mac OS X(包括 Universal、PPC 和 Intel 架构)
            assetBundleOptions = BuildAssetBundleOptions.UncompressedAssetBundle;
            targetPlatform = BuildTarget.StandaloneOSX;
#elif UNITY_STANDALONE_LINUX //Linux
            assetBundleOptions = BuildAssetBundleOptions.UncompressedAssetBundle;
            targetPlatform = BuildTarget.StandaloneLinux;
#elif UNITY_ANDROID
            assetBundleOptions = BuildAssetBundleOptions.ChunkBasedCompression;
            targetPlatform = BuildTarget.Android;
#elif UNITY_IOS
            assetBundleOptions = BuildAssetBundleOptions.ChunkBasedCompression;
            targetPlatform = BuildTarget.iOS;
#elif UNITY_WEBGL
            assetBundleOptions = BuildAssetBundleOptions.ChunkBasedCompression;
            targetPlatform = BuildTarget.WebGL;
#endif
            if (!Directory.Exists(assetBundleDirectory))
            {
                Directory.CreateDirectory(assetBundleDirectory);
            }
            else
            {
                Directory.Delete(assetBundleDirectory, true);
                Directory.CreateDirectory(assetBundleDirectory);
            }
            BuildPipeline.BuildAssetBundles(assetBundleDirectory, assetBundleOptions, targetPlatform);
        }
    }
}

# AssetBundle 的加载

  • 两种加载方式:通过网络请求加载(UnityWebRequest)、通过本地存储加载(AssetBundle.LoadFromFile ())
  • 本工具类中使用网络请求加载方式,目的是为了适配更多的设备
  • 同一个 ab 包中如果有多个同名文件,则只会加载第一个匹配的文件
  • 加载目标 ab 包前,需要先加载它的依赖 ab 包(如果存在)
  • 加载目标 ab 包后,调用委托处理其他逻辑
  • 加载的 ab 包在使用完后需要要卸载,防止占用内存
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
namespace Common
{
    /// <summary>
    ///ab 包管理器
    /// </summary>
    public class AssetBundleManager
    {
        /// <summary>
        /// 加载资源包
        /// </summary>
        /// <param name="path"> 路径 & lt;/param>
        /// <param name="action"> 委托 & lt;/param>
        /// <returns></returns>
        public static IEnumerator LoadAssetBundle(string path, Action<AssetBundle> action)
        {
            string assetBundleName = path.Split('/')[^1];
            string startPath = path.Substring(0, path.LastIndexOf('/'));
            // 获取 AssetBundles 文件
            UnityWebRequest request_0 = UnityWebRequestAssetBundle.GetAssetBundle(startPath + "/AssetBundles", 0);
            yield return request_0.SendWebRequest();
            if (request_0.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError("Failed to load AssetBundle:" + request_0.error);
            }
            else
            {
                AssetBundle bundle_0 = DownloadHandlerAssetBundle.GetContent(request_0);
                // 获取 manifest 文件
                AssetBundleManifest manifest_0 = bundle_0.LoadAsset("AssetBundleManifest") as AssetBundleManifest;
                bundle_0.Unload(false);
                // 查找并加载依赖文件
                string[] dependencies = manifest_0.GetAllDependencies(assetBundleName);
                AssetBundle[] bundles = new AssetBundle[dependencies.Length];
                for (int i = 0; i < dependencies.Length; i++)
                {
                    string dependenciesPath = startPath + '/' + dependencies[i];
                    UnityWebRequest requests = UnityWebRequestAssetBundle.GetAssetBundle(dependenciesPath, 0);
                    yield return requests.SendWebRequest();
                    if (requests.result != UnityWebRequest.Result.Success)
                    {
                        Debug.LogError("Failed to load AssetBundle:" + requests.error);
                    }
                    else
                    {
                        bundles[i] = DownloadHandlerAssetBundle.GetContent(requests);
                    }
                }
                // 取出资源
                UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(path, 0);
                yield return request.SendWebRequest();
                if (request.result != UnityWebRequest.Result.Success)
                {
                    Debug.LogError("Failed to load AssetBundle:" + request.error);
                }
                else
                {
                    AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
                    action(bundle);
                    bundle.Unload(false);
                }
                foreach (AssetBundle item in bundles)
                {
                    item.Unload(false);
                }
            }
        }
    }
}

# 使用方法

创建
点击按钮创建 ab 包,如图:img

加载

private void OnGUI()
{
    if (GUILayout.Button("LoadAssetBundle"))
    {
        this.StartCoroutine(AssetBundleManager.LoadAssetBundle(Application.streamingAssetsPath + "/AssetBundles/model.model", TestAction));
    }
}
private void TestAction(AssetBundle bundle)
{
    GameObject receive = bundle.LoadAsset<GameObject>("Cube_1");
    Instantiate(receive, Vector3.zero, Quaternion.identity);
}