Unity 关于AssetBundle(资源束)打包和加载(一)

来源:互联网 发布:mac10.9 php开发环境 编辑:程序博客网 时间:2024/04/30 01:04

在使用Unity制作大型场景的时候,往往需要加载大量的数据文件,尤其是对于模型、材质、贴图、特效等资源都是项目中不可缺少的一部分。数据量越大,数组加载就越慢,让用户长时间等待是一种非常差的体验。

因此在项目制作前必须先要解决场景数据管路的问题。Unity3D提供了一种被叫做 AssetBundles(资源束)的外部整合数据,可以供我们资源管理使用。

在游戏的运作当中,更新资源必不可少。我们可以将他们制作成Prefab,包成AssetBundle,方便我们后面使用来达到资源更新的效果。


1.首先在场景中新建3个物体,分别是:Cube,Sphere, Capsule,分别把他们拉成预制体。
这里写图片描述


2.分别点击预制体,给每个预制体设置 AssetBundle 的名字
这里写图片描述这里写图片描述这里写图片描述

这里我们对AssetBundle 下拉框这里面的选项进行一下解释!~
这里写图片描述

None: 表示AssetBundle的名称为空
New…:设置AssetBundle的名称(名称默认小写表示)
Remove Unused Names: 移除没有使用到的 AssetBundle的名称
Filter Selected Name: 筛选出使用该AssetBundle名称的所有物体


3.上面的AssetBundle的名称设置好之后,我们开始编写——打包脚本(脚本放在Editor文件夹下)

using UnityEditor;using UnityEngine;public class BuildAssetBundle{    /// <summary>    /// 点击后,所有设置了AssetBundle名称的资源会被 分单个打包出来    /// </summary>    [MenuItem("AssetBundle/Build (Single)")]    static void Build_AssetBundle()    {           BuildPipeline.BuildAssetBundles(Application.dataPath + "/Test_AssetBundle", BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);        //刷新        AssetDatabase.Refresh();    }    /// <summary>    /// 选择的资源合在一起被打包出来    /// </summary>    [MenuItem("AssetBundle/Build (Collection)")]    static void Build_AssetBundle_Collection()    {        AssetBundleBuild[] buildMap = new AssetBundleBuild[1];        //打包出来的资源包名字        buildMap[0].assetBundleName = "enemybundle";        //在Project视图中,选择要打包的对象          Object[] selects = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);        string[] enemyAsset = new string[selects.Length];        for (int i = 0; i < selects.Length; i++)        {            //获得选择 对象的路径            enemyAsset[i] = AssetDatabase.GetAssetPath(selects[i]);        }        buildMap[0].assetNames = enemyAsset;        BuildPipeline.BuildAssetBundles(Application.dataPath + "/Test_AssetBundle", buildMap, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);        //刷新        AssetDatabase.Refresh();    }}

上面打包AssetBundle的代码,主要一句

//“Application.dataPath + /Test_AssetBundle” --AssetBundle导出到的文件夹的位置//“BuildAssetBundleOptions.None” --构建AssetBundle没有任何特殊的选项//“BuildTarget.StandaloneWindows” --AssetBundle的构建平台(这个需要注意,这里测试的电脑端,Android、IOS等需要另外选择) BuildPipeline.BuildAssetBundles(Application.dataPath + "/Test_AssetBundle", BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);

打包出来的 AssetBundle
这里写图片描述
这里打包的 “enemybundle”, 我选择的是三个预设体(Cube、Sphere、Capsule)打包在了一起;


这里显示的打包出来的AssetBundle包含的物体的信息
这里写图片描述


4.打包脚本编写完成后,接下来编写——读取脚本

using System.Collections;using UnityEngine;public class LoadAssetBundle : MonoBehaviour{    public static string BundleURL;    private void Awake()    {        //平台预处理        BundleURL =#if UNITY_ANDROID                    "jar:file://" + Application.dataPath + "!/assets/";#elif UNITY_IPHONE                    Application.dataPath + "/Raw/";  #elif UNITY_STANDALONE_WIN || UNITY_EDITOR                    "file://" + Application.dataPath + "/Test_AssetBundle/";//Test_AssetBundle 资源束文件的位置 #else                    string.Empty;  #endif    }    void OnGUI()    {        if (GUI.Button(new Rect(20,20,300,100),"点击加载Asset"))        {            //BundleURL + "enemybundle" 要加载的文件地址            StartCoroutine(DownLoadAssetAndScene(BundleURL + "cub"));            //StartCoroutine(DownLoadAssetAndScene(BundleURL + "sph"));            //StartCoroutine(DownLoadAssetAndScene(BundleURL + "cap"));            //StartCoroutine(DownLoadAssetAndScene(BundleURL + "enemybundle"));        }    }    IEnumerator DownLoadAssetAndScene(string path)    {        //电脑端加载使用        WWW asset = new WWW(path);        yield return asset;        AssetBundle bundle = asset.assetBundle;        //资源加载         //加载的是打包到资源包里面,每个资源的名字        Instantiate(bundle.LoadAsset("Cube.prefab"));        //Instantiate(bundle.LoadAsset("Sphere.prefab"));        //Instantiate(bundle.LoadAsset("Capsule.prefab"));        //资源加载完毕后记得Unload,不然再次加载资源的时候无法加载        bundle.Unload(false);    }}

加载出来资源的位置就是AssetBundle时候,资源在场景中的位置。

值得一提的是,在加载完资源后立即通过AssetBundle.Unload(false)释放AssetBundle(资源束)文件本身的内存镜像,但不销毁加载的Asset(资源)对象。这样就不用保存AssetBundle(资源束)的引用,且可以立即释放一部分内存。释放时,如果有Instantiate(实例化)的对象,用Destroy(毁灭)进行销毁。

介绍几个释放代码:

  1. Destroy:主要用于销毁克隆对象,也可以用于场景内的静态物体,但不会自动释放该对象的所有引用。
  2. AssetBundle.Unload(false):释放AssetBundle(资源束)文件内存镜像。
  3. AssetBundle.Unload(true):释放AssetBundle(资源束)文件内存镜像,同时销毁所以已经Load(下载)的Assets(资源)内存对象。
  4. Resources.UnloadUnusedAssets:用于释放所以没有引用的Asset(资源)对象。

需要注意的是:**
平台为电脑端:加载AssetBundle的时候一切正常。
平台为安卓端:会出现错误。这里写图片描述

认为是加载方法的问题,目前还没找到答案!!
希望各位朋友,留言交流!!

1 0
原创粉丝点击