AssetBundle相关API的使用

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/qq_34937637/article/details/78574393

 

 

  • 使用代码打包AssetBundle

1.使用UnityEditor中的BuildPipeline.BuildAssetBundles方法,要确保保存的文件夹存在

2.注意事项:脚本要放在Assets/UnityEditor路径下,否则运行会报错

或者脚本放在其他文件夹下,可以这样:

#if UNITY_EDITOR

//用到UnityEditor命名空间下的代码

#endif

3.BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);

dir:AssetBundle要保存的路径

BuildAssetBundleOptions:build选型

BuildAssetBundleOptions.None:使用LZMA算法压缩,压缩的包更小,但是加载时间更长。使用之前需要整体解压。一旦被解压,这个包会使用LZ4重新压缩。使用资源的时候不需要整体解压。在下载的时候可以使用LZMA算法,一旦它被下载了之后,它会使用LZ4算法保存到本地上。

BuildAssetBundleOptions.UncompressedAssetBundle:不压缩,包大,加载快

BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4压缩,压缩率没有LZMA高,但是我们可以加载指定资源而不用解压全部。

注意使用LZ4压缩,可以获得可以跟不压缩想媲美的加载速度,而且比不压缩文件要小。

BuildTarget:选择build出来的AssetBundle包要使用的平台

using System.IO;
using UnityEditor;

public class CreateAssetBundles
{

    [MenuItem("Assets/Build AssetBundles")]
    static  void BuildAllAssetBundles()
    {
        string dir = "AssetBundles";

        if (!Directory.Exists(dir))
        {
            Directory.CreateDirectory(dir);
        }

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

以下是三种资源build的方式:

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;//改变添加unity编辑器类

public class AssetBundleTool
{

    [MenuItem("Tools/AssetBundle/AllBundle")]
    public static void AllBundle()
    {
        Debug.Log("启动所有的打包");
        BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetsBundle", BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
    }
    [MenuItem("Tools/AssetBundle/SingleBundle")]
    public static void SingleBundle()
    {
        Debug.Log("启动打包");
        AssetBundleBuild build = new AssetBundleBuild();
        build.assetBundleName = "prefabs";
        build.assetBundleVariant = "img";
        build.assetNames = new string[] { "Assets/Resources/Image/img" };

        AssetBundleBuild[] builds = new AssetBundleBuild[1] { build };
        BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetsBundle", builds, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);

    }

    [MenuItem("Tools/AssetBundle/SelectBundle2")]
    public static void SelectBundle2()
    {
        Dictionary<string, AssetBundleBuild> assets = new Dictionary<string, AssetBundleBuild>();
        //获取选择的资源  DeepAssets:获取所有文件夹及其子文件夹的资源
        Object[] assetObjs = Selection.GetFiltered<Object>(SelectionMode.DeepAssets);

        Debug.Log("资源的数量为:" + assetObjs.Length);
        for (int i = 0; i < assetObjs.Length; i++)
        {
            string path = AssetDatabase.GetAssetPath(assetObjs[i]);
            string assetName = AssetImporter.GetAtPath(path).assetBundleName;
            string assetVariant = AssetImporter.GetAtPath(path).assetBundleVariant;
            Debug.Log(path + "," + assetName + "," + assetVariant);

            string key = assetName + "." + assetVariant;
            if (assets.ContainsKey(key))
            {
                //更新
                AssetBundleBuild build = assets[key];
                string[] assetNames = build.assetNames;
                string[] newAssetNames = new string[assetNames.Length + 1];
                ArrayUtility.AddRange<string>(ref newAssetNames, assetNames);
                newAssetNames[assetNames.Length] = path;

                build.assetNames = newAssetNames;
                assets[key] = build;
            }
            else
            {
                if (key != null && key != "" && key.Length > 1)
                {
                    AssetBundleBuild build = new AssetBundleBuild();
                    build.assetBundleName = assetName;
                    build.assetBundleVariant = assetVariant;
                    build.assetNames = new string[1] { path };
                    assets.Add(key, build);
                }
                else
                {
                    key = path.Substring(path.LastIndexOf(".") + 1);

                    if (assets.ContainsKey(key))
                    {
                        //更新
                        AssetBundleBuild build = assets[key];
                        string[] assetNames = build.assetNames;
                        string[] newAssetNames = new string[assetNames.Length + 1];
                        ArrayUtility.AddRange<string>(ref newAssetNames, assetNames);
                        newAssetNames[assetNames.Length] = path;

                        build.assetNames = newAssetNames;
                        assets[key] = build;
                    }
                    else
                    {
                        AssetBundleBuild build = new AssetBundleBuild();
                        //build.assetBundleName = assetName;
                        //build.assetBundleVariant = assetVariant;
                        build.assetBundleName = key;
                        build.assetNames = new string[1] { path };
                        assets.Add(key, build);
                    }
                }
            }

        }

        AssetBundleBuild[] builds = new AssetBundleBuild[assets.Count];
        assets.Values.CopyTo(builds, 0);
        Debug.Log(builds.Length);
        BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetsBundle", builds, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
    }
    [MenuItem("Tools/AssetBundle/SelectBundle")]
    public static void SelectBundle()
    {
        Dictionary<string, AssetBundleBuild> assets = new Dictionary<string, AssetBundleBuild>();
        //获取所有的鼠标选择的对象
        //SelectionMode.DeepAssets:收集所有包括文件夹,Assets,子文件夹。 
        Object[] objList = Selection.GetFiltered<Object>(SelectionMode.DeepAssets);
        Debug.Log(objList.Length);
        for (var i = 0; i < objList.Length; i++)
        {
            //获取该对象的在资源文件夹中的相对路径
            string path = AssetDatabase.GetAssetPath(objList[i]);
            Debug.Log(path);
            //通过路径返回资源设置好的资源包的名字AssetBundleName
            string assetName = AssetImporter.GetAtPath(path).assetBundleName;
            //返回该对象的assetBundleVariant;
            string variant = AssetImporter.GetAtPath(path).assetBundleVariant;
            string key = assetName + "." + variant;
            //Debug.Log (key);
            if (assets.ContainsKey(key))
            {
                //原基础更新
                AssetBundleBuild build = assets[key];
                build.assetNames = AppendChild(build.assetNames, path);
                assets[key] = build;
            }
            else
            {
                if (key != null && key != "" && key.Length > 1)
                {
                    Debug.Log("456");
                    AssetBundleBuild build = new AssetBundleBuild();
                    build.assetBundleName = assetName;
                    build.assetBundleVariant = variant;
                    build.assetNames = new string[] { path };
                    assets.Add(key, build);
                }
                else
                {
                    key = path.Substring(path.LastIndexOf(".") + 1);
                    Debug.Log(key);
                    if (assets.ContainsKey(key))
                    {
                        //原基础更新
                        AssetBundleBuild build = assets[key];
                        build.assetNames = AppendChild(build.assetNames, path);
                        assets[key] = build;
                    }
                    else
                    {

                        AssetBundleBuild build = new AssetBundleBuild();
                        build.assetBundleName = key;
                        build.assetNames = new string[] { path };
                        assets.Add(key, build);
                    }

                }
            }
        }
        //启动打包
        AssetBundleBuild[] crr = new AssetBundleBuild[assets.Count];
        assets.Values.CopyTo(crr, 0);
        Debug.Log(crr[0].assetBundleName);
        BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetsBundle", crr, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
    }
    static string[] AppendChild(string[] arr, string value)
    {
        string[] brr = new string[arr.Length + 1];
        for (var i = 0; i < arr.Length; i++)
        {
            brr[i] = arr[i];
        }
        brr[brr.Length - 1] = value;
        return brr;
    }
}

 

  • AssetBundle的加载和使用

1.使用AssetBundle.LoadFromFile方法加载保存在文件夹中的AssetBundle

2.使用AssetBundle.LoadAsset方法取得prefab

3.AssetBundle ab2 = AssetBundle.LoadFromFile("AssetBundles/scene/share.unity3d");先获得共享包share.unity3d(包含prefab引用的材质),

否则prefab会丢失材质(material)

using UnityEngine;

public class LoadFromAssetBundle : MonoBehaviour {

	void Start () {
        AssetBundle ab2 = AssetBundle.LoadFromFile("AssetBundles/scene/share.unity3d");
        AssetBundle ab = AssetBundle.LoadFromFile("AssetBundles/scene/cube.unity3d");
        GameObject cubePrefab = ab.LoadAsset<GameObject>("CubeWall");

        Instantiate(cubePrefab);
	}
}

 

 

  • 加载AssetBundle的方式

1.第一种加载AB的方式LoadFromMemoryAsync(异步),LoadFromMemory(同步)

using UnityEngine;
using System.IO;
using System.Collections;

public class LoadFromAssetBundle : MonoBehaviour {
    

	IEnumerator Start () {
        string path1 = "AssetBundles/scene/cube.unity3d";
        string path2 = "AssetBundles/scene/share.unity3d";


        #region  第一种加载AB的方式LoadFromMemoryAsync(异步),LoadFromMemory(同步)
        AssetBundleCreateRequest request1 = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path1));
        yield return request1;
        AssetBundleCreateRequest request2 = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path2));
        yield return request2;
        AssetBundle ab1 = request1.assetBundle;
        //LoadFromMemory(同步)
        //AssetBundle ab1 = AssetBundle.LoadFromMemory(File.ReadAllBytes(path1));
        //AssetBundle ab2 = AssetBundle.LoadFromMemory(File.ReadAllBytes(path2));
        #endregion

       
        //使用里面的资源
        GameObject cubePrefab = ab1.LoadAsset<GameObject>("CubeWall");
        Instantiate(cubePrefab);
    }
}

2.第二种加载AB的方式LoadFromFile(同步),LoadFromFileAsync(异步)

using UnityEngine;
using System.IO;
using System.Collections;

public class LoadFromAssetBundle : MonoBehaviour {
    

	IEnumerator Start () {
        string path1 = "AssetBundles/scene/cube.unity3d";
        string path2 = "AssetBundles/scene/share.unity3d";


        #region 第二种加载AB的方式LoadFromFile(同步),LoadFromFileAsync(异步)
        //AssetBundle ab1 = AssetBundle.LoadFromFile(path1);
        //AssetBundle ab2 = AssetBundle.LoadFromFile(path2);
        //LoadFromFileAsync(异步)
        AssetBundleCreateRequest request1 = AssetBundle.LoadFromFileAsync(path1);
        yield return request1;
        AssetBundleCreateRequest request2 = AssetBundle.LoadFromFileAsync(path2);
        yield return request2;
        AssetBundle ab1 = request1.assetBundle;
        #endregion

        //使用里面的资源
        GameObject cubePrefab = ab1.LoadAsset<GameObject>("CubeWall");
        Instantiate(cubePrefab);
    }
}


3.第三种加载AB的方式WWW.LoadFromCacheOrDownload(全路径)

注意:此方式将会被弃用,换成第四种方式UnityWebRequest

using UnityEngine;
using System.IO;
using System.Collections;

public class LoadFromAssetBundle : MonoBehaviour {
    
        #region 第二种加载AB的方式LoadFromFile(同步),LoadFromFileAsync(异步)
        //AssetBundle ab1 = AssetBundle.LoadFromFile(path1);
        //AssetBundle ab2 = AssetBundle.LoadFromFile(path2);
        //LoadFromFileAsync(异步)
        //AssetBundleCreateRequest request1 = AssetBundle.LoadFromFileAsync(path1);
        //yield return request1;
        //AssetBundleCreateRequest request2 = AssetBundle.LoadFromFileAsync(path2);
        //yield return request2;
        //AssetBundle ab1 = request1.assetBundle;
        #endregion

        #region 第三种加载AB的方式WWW
        while (Caching.ready == false)
        {
            yield return null;
        }
        WWW www = WWW.LoadFromCacheOrDownload(@"file://D:\Program Files (x86)\Unity3Documents\AssetBundle\AssetBundles\scene\cube.unity3d", 1);
        WWW www2 = WWW.LoadFromCacheOrDownload(@"file://D:\Program Files (x86)\Unity3Documents\AssetBundle\AssetBundles\scene\share.unity3d", 1);
        yield return www;
        yield return www2;
        if (!string.IsNullOrEmpty(www.error))
        {
            Debug.Log(www.error);
            yield break;
        }

        AssetBundle ab1 = www.assetBundle;
        #endregion

        //使用里面的资源
        GameObject cubePrefab = ab1.LoadAsset<GameObject>("CubeWall");
        Instantiate(cubePrefab);
    }
}

4.第四种加载AB的方式 UnityWebRequest.GetAssetBundle(使用命名空间using UnityEngine.Networking)

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class LoadFromAssetBundle : MonoBehaviour {
    

	IEnumerator Start () {
        
        #region 第四种加载AB的方式 UnityWebRequest.GetAssetBundle

        string uri1 = @"http://ccop.cn/AssetBundles/scene/cube.unity3d";
        UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri1);
        yield return request.Send();
        string uri2 = @"http://ccop.cn/AssetBundles/scene/share.unity3d";
        UnityWebRequest request2 = UnityWebRequest.GetAssetBundle(uri2);
        yield return request2.Send();
        //第一种方式获取AssetBundle
     AssetBundle ab1 = DownloadHandlerAssetBundle.GetContent(request);
     DownloadHandlerAssetBundle.GetContent(request2);
     //第二种方式获取AssetBundle
     //AssetBundle ab1 = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
     //AssetBundle ab2 = (request2.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
        #endregion


        //使用里面的资源
        GameObject cubePrefab = ab1.LoadAsset<GameObject>("CubeWall");
        Instantiate(cubePrefab);
    }
}

 

 

  • 从AssetBundle中获取资源(AssetBundle的使用)

1.获取对象

GameObject gameObject = loadedAssetBundle.LoadAsset<GameObject>(assetName);
Unity.Object[] objectArray = loadedAssetBundle.LoadAllAssets();

2.加载Manifests文件可以处理资源的依赖

AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
string[] dependencies = manifest.GetAllDependencies("assetBundle"); //Pass the name of the bundle you want the dependencies for.
foreach(string dependency in dependencies)
{
    AssetBundle.LoadFromFile(Path.Combine(assetBundlePath, dependency));
}

 

 

  • AssetBundle的卸载

卸载有两个方面:
1,减少内存使用
2,有可能导致丢失
所以什么时候去卸载资源
AssetBundle.Unload(true)卸载所有资源,即使有资源被使用着
(1,在关切切换、场景切换2,资源没被用的时候 调用)
AssetBundle.Unload(false)卸载所有没用被使用的资源
个别资源怎么卸载1,通过 Resources.UnloadUnusedAssets.2,场景切换的时候

后续边学习边更新。。。

(敬请期待)

猜你喜欢

转载自blog.csdn.net/qq_34937637/article/details/78574393