AssetBundles

在使用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();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

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

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

打包出来的 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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

加载出来资源的位置就是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的时候一切正常。 
平台为安卓端:会出现错误。这里写图片描述

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值