您现在的位置:首页 >> 前端 >> 内容

Unity学习之AssetBundle基础和构建使用讲解

时间:2018/6/2 13:45:35 点击:

  核心提示:AssetBundle是什么AssetBundle是Unity引擎提供的一种资源管理技术,可以用来动态的加载卸载资源,减少运行时内存压力,所以也是一种热更新技术。它是一种特定的压缩包,它可以包含模型,...

AssetBundle是什么

AssetBundle是Unity引擎提供的一种资源管理技术,可以用来动态的加载卸载资源,减少运行时内存压力,所以也是一种热更新技术。它是一种特定的压缩包,它可以包含模型,材质,预设包,音频,甚至整个场景。

构建AssetBundle

创建一个名为Editor的文件夹,新建一个C#脚本BuildAssetBundle

using UnityEngine;
using UnityEditor;
using System.IO;

public class BuildAssetBundle {

    [MenuItem("AssetBundleTools/BuildAllAssetBundles")]
    public static void buildAllAssetBundle()
    {
        string outPath = string.Empty;
        outPath = Application.streamingAssetsPath;
        if(!Directory.Exists(outPath))
        {
            Directory.CreateDirectory(outPath);
        }
        BuildPipeline.BuildAssetBundles(outPath, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
    }
}

该脚本会创建一个名为“AssetBundleTools”的菜单项,点击里面的“BuildAllAssetBundles”会执行这段代码。

这里会自动创建一个StreamingAssets文件夹,这是我们要打包的输出路径,StreamingAssets是一个特殊文件夹,放在这里的资源在打包成apk或ipa是不会被压缩的,当然你也可以打包进AssetBundles文件夹。

AssetBundle的压缩方式:

在这之前先说一下LZMA和LZ4这两种压缩方式:

LZMA压缩方式会让文件大小尽可能的小,但是在使用之前需要对整个包解压缩,解压缩的过程可能会导致稍长的加载时间。

LZ4压缩方式会比LZMA压缩的文件大,但是在使用时不需要对整个包进行解压,它是基于“块”的压缩算法,可对单个块解压,速度会更快。

BuildPipeline.BuildAssetBundles这个是打包资源的关键方法,里面有3个参数:

- 第一个是打包的输出路径

- 第二个BuildAssetBundleOptions是打包的设置参数,有3种方式

BuildAssetBundleOptions.None:使用LZMA格式压缩。在使用这种包时会先解压缩,然后使用LZ4格式在磁盘上重新压缩。一般适用于需要从网络上下载的小文件。

BuildAssetBundleOptions.UncompressedAssetBundle:不压缩,缺点是文件大,但是加载快。

BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4方式压缩。

- 第三个参数是目标平台,这里使用Windows64

在unity里标记需要打包的资源

Unity学习之AssetBundle基础和构建使用讲解

在运行脚本时会将所有标记了AssetBundle名称的资源打包进目标文件夹中。

打包完成后在目标文件夹里会生成的文件,这里我只打包了一个perfab,会生成这4个文件<喎?http://www.weiyer.com/Search.asp?KeyWord=/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxpbWcgYWx0PQ=="这里写图片描述" src="/uploadfile/Collfiles/20180531/20180531091624132.png" title="\" />

输出到这个目标文件夹的所有资源都会有一个与之名称想对应的.manifest文件,包括这个目标文件夹本身,所以会有StreamingAssets和StreamingAssets.manifest这两个文件。perfab1就是上面我们自己标记的打包资源,同样也对应了一个perfab1.manifest文件。

现在资源有了,我们需要动态加载它。

加载AssetBundle

Unity中提供了4中方式来加载AssetBundle:

1. AssetBundle.LoadFromMemoryAsync

从内存异步加载AssetBundle

public class Example : MonoBehaviour
{
    IEnumerator LoadFromMemoryAsync(string path)
    {
        AssetBundleCreateRequest createRequest = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
        yield return createRequest;
        AssetBundle bundle = createRequest.assetBundle;
        var prefab = bundle.LoadAsset("MyObject");
        Instantiate(prefab);
    }
}

2.AssetBundle.LoadFromFile

从本地加载,速度最快。

如果是未压缩或者LZ4压缩的,从本地直接读取。

如果是LZMA压缩的,先解压缩包,然后加载到内存中。

public class LoadFromFileExample extends MonoBehaviour {
    function Start() {
        var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
        if (myLoadedAssetBundle == null) {
            Debug.Log("Failed to load AssetBundle!");
            return;
        }
        var prefab = myLoadedAssetBundle.LoadAsset.("MyObject");
        Instantiate(prefab);
    }
}

3.WWW.LoadfromCacheOrDownload

从本地或远程服务器加载,Unity官方文档里已经标记为即将被弃用,建议使用UnityWebRequest

4.UnityWebRequest的DownloadHandlerAssetBundle(Unity 5.3 or newer)

IEnumerator InstantiateObject()
    {
        string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
        UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(uri);
        yield return request.SendWebRequest();
        AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
        GameObject cube = bundle.LoadAsset("Cube");
        GameObject sprite = bundle.LoadAsset("Sprite");
        Instantiate(cube);
        Instantiate(sprite);
    }

资源卸载

AssetBundle.Unload(true)

只释放AssetBundle压缩包本身

AssetBundle.Unload(false)

释放压缩包以及从压缩包里加载(LoadAsset)出来的资源

Resources.UnloadUnusedAssets()

释放没有引用的资源

Resources.UnloadAsset(obj)

释放指定资源

AssetBundle依赖关系

在Unity5之后的版本只自动处理依赖关系,打包时会把依赖关系存储在manifest清单文件里,我们也可以通过加载manifest来动态获取依赖关系。

加载方式跟加载AssetBundle包一样:

AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset("AssetBundleManifest");
string[] dependencies = manifest.GetAllDependencies("assetBundle");
foreach(string dependency in dependencies)
{
    AssetBundle.LoadFromFile(Path.Combine(assetBundlePath, dependency));
}

可以直接通过GetAllDependencies方法获取到一个名为“assetBundle”的包的所有依赖项,然后加载它的依赖项。

Tags:UN NI IT TY 
作者:网络 来源:鬼雨的博客