如何使用Assetsbundle打包,下载,加载

Directory 类   在system.io空间下,负责目录的管理和创建。Exists判断是否有该目录。
原文地址:http://blog.csdn.net/cuiyh1993/article/details/52245337

打包:打包的功能一定要放在Editor文件夹下,不然编译过程会出错。Editor文件夹下的脚本不能进行挂载。
using UnityEngine;  
using System.Collections;  
using System.IO;  
using System.Collections.Generic;  
using System;  
using UnityEditor;  
  
/// <summary>  
/// 创建AssetBundle  
/// </summary>  
public class CreateAssetBundle : MonoBehaviour  
{  
    //生成到的目录  
    public static string Build2Path = Application.dataPath + "/BuildABs";  
  
    public static BuildTarget target = BuildTarget.iOS;  
  
    [MenuItem("CYH_Tools/AB_Packager/Build_2_IPhone")]  
    public static void BuildiPhoneResource()  
    {  
        target = BuildTarget.iOS;  
        BuildAssetResource(target);  
    }  
  
    [MenuItem("CYH_Tools/AB_Packager/Build_2_Android")]  
    public static void BuildAndroidResource()  
    {  
        target = BuildTarget.Android;  
        BuildAssetResource(target);  
    }  
  
    [MenuItem("CYH_Tools/AB_Packager/Build_2_Windows")]  
    public static void BuildWindowsResource()  
    {  
        target = BuildTarget.StandaloneWindows;  
        BuildAssetResource(target);  
    }  
  
    private static void BuildAssetResource(BuildTarget target)  
    {  
        //文件已经存在就删除  
        if (Directory.Exists(Build2Path))  
        {  
            Directory.Delete(Build2Path, true);  
        }  
        //文件不存在就创建  
        if (!Directory.Exists(Build2Path))  
        {  
            Directory.CreateDirectory(Build2Path);  
        }  
  
        //打包  
        BuildPipeline.BuildAssetBundles(Build2Path,BuildAssetBundleOptions.None,target);  
    }  
}

下载到本地,与资源的加载。这里的mono可以不继承,这样单例就可以简单一些,而且不需要挂载,但是底下的开启协程就要写的长一点(还要用mono对象去调用StartCoroutine)。

using System.Collections;
using System.IO;
using System.Collections.Generic;
using System;

public delegate void dlg_OnAssetBundleDownLoadOver();
/// <summary>  
/// 加载AssetBundle  
/// </summary>  
public class LoadAssetBundle :MonoBehaviour
{
    public static LoadAssetBundle Instance ;
     void Awake() {
        Instance = this;
    }
    //不同平台下StreamingAssets的路径设置  
//    public static readonly string PathURL =
//#if UNITY_ANDROID
//        "jar:file://" + Application.dataPath + "!/assets/";  
//#elif UNITY_IPHONE
//        Application.dataPath + "/Raw/";    
//#elif UNITY_STANDALONE_WIN || UNITY_EDITOR
//        "file://" + Application.dataPath + "/StreamingAssets/";
//#else
//        string.Empty;    
//#endif

//5.0版本打包时候选中需要打包的东西然后设置右下角名称,同个/设置多集目录,后面的框标记后缀(后缀不重要)  
    //打包时候的目标文件夹,假设目标文件夹名称为"WJJ",那么会生成"WJJ"和"WJJ.manifest"两个文件  
    //其中WJJ.manifest文件没有用,只是用来看的,WJJ是一个assetbundle包,里面包含了整个文件夹的依赖信息  
    //可以先加载这个东西,然后获取到依赖关系后逐步加载  
    //递一般归加载并保存到Application.persistentDataPath  
    //注意用GetDirectDependencies递归,不要用GetAllDependencies,因为已经包含孙子儿子又会加载孙子,重复加载了  
    //简单用法直接获取不要用GetAllDependencies,然后倒序加载

/// <summary>  
        /// 下载资源到本地包括它的依赖项  
        /// </summary>  
        /// <param name="AssetsHost">根目录地址</param>  
        /// <param name="RootAssetsName"></param>  
        /// <param name="AssetName"></param>  
        /// <param name="savePath"></param>  
    public void DownLoadAssets2LocalWithDependencies(string AssetsHost, string RootAssetsName, string AssetName, string savePath, dlg_OnAssetBundleDownLoadOver OnDownloadOver = null)
    {
       
        StartCoroutine(DownLoadAssetsWithDependencies2Local(AssetsHost, RootAssetsName, AssetName, savePath, OnDownloadOver));
    }

/// <summary>  
        ///   //从服务器下载到本地  
        /// </summary>  
        /// <param name="AssetsHost">服务器路径</param>  
        /// <param name="RootAssetsName">总依赖文件目录路径</param>  
        /// <param name="AssetName">请求资源名称</param>  
        /// <param name="saveLocalPath">保存到本地路径,一般存在Application.persistentDataPath</param>  
        /// <returns></returns>  
    IEnumerator DownLoadAssetsWithDependencies2Local(string AssetsHost, string RootAssetsName, string AssetName, string saveLocalPath, dlg_OnAssetBundleDownLoadOver OnDownloadOver = null)
    {
        WWW ServerManifestWWW = null;        //用于存储依赖关系的 AssetBundle  
        AssetBundle LocalManifestAssetBundle = null;    //用于存储依赖关系的 AssetBundle  
        AssetBundleManifest assetBundleManifestServer = null;  //服务器 总的依赖关系      
        AssetBundleManifest assetBundleManifestLocal = null;   //本地 总的依赖关系

if (RootAssetsName != "")    //总依赖项为空的时候去加载总依赖项  
        {
            ServerManifestWWW = new WWW(AssetsHost + "/" + RootAssetsName);

Debug.Log("___当前请求总依赖文件~\n");

yield return ServerManifestWWW;
            if (ServerManifestWWW.isDone)
            {
                //加载总的配置文件  
                assetBundleManifestServer = ServerManifestWWW.assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
                Debug.Log("___当前请求总依赖文件~\n");
            }
            else
            {
                throw new Exception("总依赖文件下载失败~~~\n");
            }
        }

//获取需要加载物体的所有依赖项  
        string[] AllDependencies = new string[0];
        if (assetBundleManifestServer != null)
        {
            //根据名称获取依赖项  
            AllDependencies = assetBundleManifestServer.GetAllDependencies(AssetName);
        }

//下载队列 并获取每个资源的Hash值  
        Dictionary<string, Hash128> dicDownloadInfos = new Dictionary<string, Hash128>();
        for (int i = AllDependencies.Length - 1; i >= 0; i--)
        {
            dicDownloadInfos.Add(AllDependencies[i], assetBundleManifestServer.GetAssetBundleHash(AllDependencies[i]));
        }
        dicDownloadInfos.Add(AssetName, assetBundleManifestServer.GetAssetBundleHash(AssetName));
        if (assetBundleManifestServer != null)   //依赖文件不为空的话下载依赖文件  
        {
            Debug.Log("Hash:" + assetBundleManifestServer.GetHashCode());
            dicDownloadInfos.Add(RootAssetsName, new Hash128(0, 0, 0, 0));
        }

//卸载掉,无法同时加载多个配置文件  
        ServerManifestWWW.assetBundle.Unload(true);

if (File.Exists(saveLocalPath + "/" + RootAssetsName))
        {
            LocalManifestAssetBundle = AssetBundle.LoadFromFile(saveLocalPath + "/" + RootAssetsName);
            assetBundleManifestLocal = LocalManifestAssetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }

foreach (var item in dicDownloadInfos)
        {
            if (!CheckLocalFileNeedUpdate(item.Key, item.Value, RootAssetsName, saveLocalPath, assetBundleManifestLocal))
            {
                Debug.Log("无需下载:" + item.Key);
                continue;
            }
            else
            {
                DeleteFile(saveLocalPath + "/" + item.Key);
            }

//直接加载所有的依赖项就好了  
            WWW wwwAsset = new WWW(AssetsHost + "/" + item.Key);
            //获取加载进度  
            while (!wwwAsset.isDone)
            {
                Debug.Log(string.Format("下载 {0} : {1:N1}%", item.Key, (wwwAsset.progress * 100)));
                yield return new WaitForSeconds(0.2f);
            }
            //保存到本地  
            SaveAsset2LocalFile(saveLocalPath, item.Key, wwwAsset.bytes, wwwAsset.bytes.Length);

}

if (LocalManifestAssetBundle != null)
        {
            LocalManifestAssetBundle.Unload(true);
        }

if (OnDownloadOver != null)
        {
            OnDownloadOver();
        }
    }

/// <summary>  
        /// 检测本地文件是否存在已经是否是最新  
        /// </summary>  
        /// <param name="AssetName"></param>  
        /// <param name="RootAssetsName"></param>  
        /// <param name="localPath"></param>  
        /// <param name="serverAssetManifestfest"></param>  
        /// <param name="CheckCount"></param>  
        /// <returns></returns>  
    bool CheckLocalFileNeedUpdate(string AssetName, Hash128 hash128Server, string RootAssetsName, string localPath, AssetBundleManifest assetBundleManifestLocal)
    {
        Hash128 hash128Local;
        bool isNeedUpdate = false;
        if (!File.Exists(localPath + "/" + AssetName))
        {
            return true;   //本地不存在,则一定更新  
        }

if (!File.Exists(localPath + "/" + RootAssetsName))   //当本地依赖信息不存在时,更新  
        {
            isNeedUpdate = true;
        }
        else   //总的依赖信息存在切文件已存在  对比本地和服务器两个文件的Hash值  
        {
            if (hash128Server == new Hash128(0, 0, 0, 0))
            {
                return true;  //保证每次都下载总依赖文件  
            }
            hash128Local = assetBundleManifestLocal.GetAssetBundleHash(AssetName);
            //对比本地与服务器上的AssetBundleHash  版本不一致就下载  
            if (hash128Local != hash128Server)
            {
                isNeedUpdate = true;
            }
        }
        return isNeedUpdate;
    }

/// <summary>  
        /// 非递归式加载指定AB,并加载依赖项,并返回目标GameObject  
        /// </summary>  
        /// <param name="RootAssetsName"></param>  
        /// <param name="AssetName"></param>  
        /// <param name="LocalPath"></param>  
    public GameObject GetLoadAssetFromLocalFile(string RootAssetsName, string AssetName, string PrefabName, string LocalPath)
    {//这里还没有对没用到的资源进行释放。
        AssetBundle assetBundle = AssetBundle.LoadFromFile(LocalPath + "/" + RootAssetsName);
        AssetBundleManifest assetBundleManifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

string[] AllDependencies = assetBundleManifest.GetAllDependencies(AssetName);

for (int i = AllDependencies.Length - 1; i >= 0; i--)
        {
            AssetBundle assetBundleDependencies = AssetBundle.LoadFromFile(LocalPath + "/" + AllDependencies[i]);
            assetBundleDependencies.LoadAllAssets();
        }
        print(LocalPath + "/" + AssetName);
        AssetBundle assetTarget = AssetBundle.LoadFromFile(LocalPath + "/" + AssetName);
        return assetTarget.LoadAsset<GameObject>(PrefabName);
    }

/// <summary>  
        /// 递归加载本地所有依赖项  
        /// </summary>  
        /// <param name="RootAssetsName"></param>  
        /// <param name="AssetName"></param>  
        /// <param name="LocalPath"></param>  
    AssetBundleManifest assetBundleManifestLocalLoad;   //递归加载时候用  
    public void RecursionLoadAssetFromLocalFile(string RootAssetsName, string AssetName, string LocalPath, int RecursionCounter)
    {
        if (RecursionCounter++ == 0)
        {
            //加载本地Manifest获取依赖项  
            assetBundleManifestLocalLoad = AssetBundle.LoadFromFile(LocalPath + "/" + RootAssetsName).LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }

//当前AssetName所有依赖项  
        string[] AllDependencies = assetBundleManifestLocalLoad.GetDirectDependencies(AssetName);

for (int i = 0; i < AllDependencies.Length; i++)
        {
            RecursionLoadAssetFromLocalFile(RootAssetsName, AllDependencies[i], LocalPath, RecursionCounter);
        }

AssetBundle assetBundle = AssetBundle.LoadFromFile(LocalPath + "/" + AssetName);
        assetBundle.LoadAllAssets();
    }

/// <summary>  
        /// 将文件模型创建到本地  
        /// </summary>  
        /// <param name="path"></param>  
        /// <param name="name"></param>  
        /// <param name="info"></param>  
        /// <param name="length"></param>  
    void SaveAsset2LocalFile(string path, string name, byte[] info, int length)
    {
        Stream sw = null;
        FileInfo fileInfo = new FileInfo(path + "/" + name);
        if (fileInfo.Exists)
        {
            fileInfo.Delete();
        }

//如果此文件不存在则创建  
        sw = fileInfo.Create();
        //写入  
        sw.Write(info, 0, length);

sw.Flush();
        //关闭流  
        sw.Close();
        //销毁流  
        sw.Dispose();

Debug.Log(name + "成功保存到本地~");
    }

/// <summary>  
        /// 删除文件  
        /// </summary>  
        /// <param name="path"></param>  
    void DeleteFile(string path)
    {
        File.Delete(path);
    }
}

测试代码:
这里是从本地文件夹下进行下载与加载的,所以前面加上file://   
要注意调用函数的时候,下载时第一个是下载路径,然后是总依赖关系,文件名(要带拓展名),保存路径,下载后要执行的无参的函数。
加载时参数是总依赖关系,文件名(要带拓展名),预制体名,保存AB包的路径

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class text : MonoBehaviour
{
void Start()  
{
        //5.0版本打包时候选中需要打包的东西然后设置右下角名称,同个/设置多集目录,后面的框标记后缀(后缀不重要)  
        //打包时候的目标文件夹,假设目标文件夹名称为"WJJ",那么会生成"WJJ"和"WJJ.manifest"两个文件  
        //其中WJJ.manifest文件没有用,只是用来看的,WJJ是一个assetbundle包,里面包含了整个文件夹的依赖信息  
        //可以先加载这个东西,然后获取到依赖关系后逐步加载

string savePath = Application.persistentDataPath;
        print(savePath);
        string path = "file://"+Application.dataPath;
        print(path);
        try
        {
            LoadAssetBundle.Instance.DownLoadAssets2LocalWithDependencies(path+"/BuildABs", "BuildABs", "cube.u3d", savePath, () =>
            {
                GameObject obj = LoadAssetBundle.Instance.GetLoadAssetFromLocalFile("BuildABs", "cube.u3d", "Cube", Application.persistentDataPath);
                GameObject.Instantiate(obj);
                print(obj.name);
                //obj.GetComponent<Renderer>().sharedMaterial.shader = Shader.Find(obj.GetComponent<Renderer>().sharedMaterial.shader.name);  
            });

}
        catch (Exception ex)
        {
            Debug.Log(ex.Message);
        }
    }

自动设置AssetBundle名称:只要资源设置了AssetBundle名称,BuildPipeline.BuildAssetBundles函数就可以将此资源打包。但是如果一个模型Model带有一个材质Mat,只把Model设置了AssetBundle名称,打包时Mat将会被一起打包到Model的资源包中,这就产生了一个问题,如果多个模型公用一个Mat,那么Mat就会被重复打包进多个资源中,因此建议将公用的资源(材质、贴图等等)全部设置AssetBundle名称,从而进行分开打包,而模型单独使用的资源可以打包到一起。那么涉及到如果项目有几百甚至更多的资源需要打包的话,手动设置AssetBundle名称会太费时,因此可以将打包的资源放置在一个文件夹中,然后通过AssetDatabase.GetDependencies()函数来获取某个模型的依赖资源、AssetImporter.GetAtPath()获取资源的打包信息、AssetDatabase.AssetPathToGUID()来获取资源的哈希ID,然后调用AssetImporter.assetBundleName属性,用资源的哈希ID设置依赖资源的AssetBundle名称,最后再分离打包。注意:打包前一定要将AssetBundle的名称先清以下,防止重复打包。

时间: 2024-11-10 01:12:49

如何使用Assetsbundle打包,下载,加载的相关文章

Unity5 AssetBundle 打包以及加载

using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEditor; using System.IO; public class BuildAssetBundle : Editor { //需要打包的路径,根据项目具体需求自己定 private static string assetPath = "AllAssets"; //导出包路径 private stat

[Unity]浅谈AssetBundle的依赖关系打包与加载

一.写在前面 通过AssetBundle进行资源管理很方便.AssetBundle的打包与加载策略有很多种,本文来讲一种可以随意通过资源名来加载指定目录下资源的打包方法.意在加深对资源管理的理解. 二.策略介绍 1.打包的粒度划分的策略 ①     所有在指定目录下的文件,即RootList,都被打包成单独结点 ②     对于RootList所依赖的所有资源,即DepList,依赖数大于1的,被打包成单独结点,等于1的,向上合并至被依赖结点. ③     记录打包信息 2.下载策略 ①    

u3d外部资源 打包与加载的问题

被坑了一下午,调bug,u3d外部加载资源一会可以,一会不行,始终找不到问题,最后快下班的时候,重新试了一下,原来是资源打包之前的文件名,和之后的加载资源名必须一样 [MenuItem("Custom Editor/Build AssetBundle From Selection Twice")] static void ExportResourceNoTrack() { // Bring up save panel string path = EditorUtility.SaveFi

AssetBundle资源打包与加载

AssetBundle资源打包  1.AssetLabels资源标签 文件名:资源打包成AssetBundle后的文件名,类似于压缩包的名字 后缀:自定义 文件名和后缀名都是小写格式(大写会自动转为小写)2. BuildPipeline.BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform) 打包所有设置了AssetLabel的资源 o

【Unity3d】3d网页游戏场景打包与加载

http://www.cnblogs.com/dosomething/archive/2012/04/07/2436353.html 3d游戏中  一个场景往往比较大  如果游戏的进行需要下载一个10M甚至更大的场景时  加载所用的时间会导致很大部分玩家的流失 我们知道unity3d中的内置地形是使用一张高度图  加载场景时  首先加载地形并显示  再去加载场景中的部件(比如树.房子等)  将会很有必要 在加载场景中的部件时  可以根据玩家当前所在的位置  由近到远的去加载 场景中的每个部件实际

Unity3d 5.x AssetBundle打包与加载

1.AssetBundle打包 unity 5.x版本AssetBundle打包,只需要设置好AssetBundle的名称后,unity会自动将其打包,无需处理其他,唯独需要做的是设置好个AssetBundle的名称. 注意:AssetBunlde的名称只能设置小写字母,即使你写成大写也会被自动转置成大写字母,而且名称中支持"/",如:"AssetBundles/cube.unity3d",.unity3d的后缀是自己设置的,可以不设置 代码: using Unit

解决vue-cli webpack打包后加载资源的路径问题

vue项目,访问打包后的项目,输入路径后,页面加载空白.这时会有两类问题,都是路径问题. 1.一个是css,js,ico等文件加载不到,是目录里少了dist 打开页面时一片空白 解决办法: 前端精品教程:百度网盘下载 config/index.js文件的build->assetsPublicPath的默认值改为 './' assetsPublicPath:资源的根目录.这个是通过http服务器运行的url路径.因为webapp和static中间还有层dist,所以要用'./' 2.另一个就是单纯

记一次webpack打包样式加载问题

今天是周六. 我过来加班了. 是因为一个属性问题. 俗话说一杯茶一包烟一个bug改一天 感觉这句话就是特意为我准备的(我加班的时候喝奶茶,抽烟,而且就一个bug.哈哈哈哈哈哈哈哈哈哈或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或或) 言归正传,说下webpack打包问题,刚到新工作和大佬们一起做ts + vue + vant的项目.(我之前不写ts,其实差不多,就是命名语法等问题) 我们一起撸代码,一直是在本地run serve的本地是

webpack打包懒加载

lazyload https://webpack.js.org/guides/lazy-loading/ 懒加载 -- 按需加载. Lazy, or "on demand", loading is a great way to optimize your site or application. This practice essentially involves splitting your code at logical breakpoints, and then loading

带你实现开发者头条APP(五)--RecyclerView下拉刷新上拉加载

转载请注明出处:http://blog.csdn.net/lowprofile_coding/article/details/51321896 一 .前言 最近实在太忙,一个多礼拜没有更新文章了,于是今晚加班加点把demo写出来,现在都12点了才开始写文章. 1.我们的目标 把RecyclerView下拉刷新上拉加载更多加入到我们的开发者头条APP中. 2.效果图 3.实现步骤 找一个带上拉刷新下载加载更多的RecyclerView开源库,我们要站在巨人的肩膀上 下载下来自己先运行下demo,然