[Unity Asset]AssetBundle系列——游戏资源打包

转载:http://www.cnblogs.com/sifenkesi/p/3557231.html

将本地资源打包,然后放到资源服务器上供游戏客户端下载或更新。服务器上包含以下资源列表:
(1)游戏内容资源assetbundle
(2)资源维护列表,包含每个资源的名字(完整路径名)和对应的版本号[资源名,版本号],如下表所示(VersionNum.xml):

<VersionNum>
  <File FileName="Assets.Resources.BigLevelTexture.TestLevel.assetbundle" Num="1" />
  <File FileName="Assets.Resources.EquipmentTexture.Test001.assetbundle" Num="1" />
  <File FileName="Assets.Resources.EquipmentTexture.Test002.assetbundle" Num="1" />
  <File FileName="Assets.Resources.EquipmentTexture.Test003.assetbundle" Num="1" />
  <File FileName="Assets.Resources.EquipmentTexture.Test004.assetbundle" Num="1" />
  <File FileName="Assets.Resources.PetTexture.Empty.assetbundle" Num="1" />
</VersionNum>

那么本地客户端的资源打包编辑器就需要完成以下工作:将资源打包、生成版本号。
我们采用通过MD5码对比的方式来对版本号进行管理,如果某资源的MD5码变更了,则将其版本号+1,否则不变。那么,可以将编辑器的具体任务划分如下:
(1)将资源打包成assetbundle,并放到指定目录下
(2)为每个assetbund生成最新MD5码,用于检查资源是否有修改
(3)比较新旧MD5码列表,产生资源变更列表,对于每个变更的资源,将其版本号+1
(4)将变更列表文件也打包成assetbundle

各个平台使用的资源包时各自独立的,打包资源代码时的选项不一样,编辑器界面如下,图2中的4个按钮每个对应上述的一步操作:

最终生成的资源目录结构如下所示:

编辑器代码如下所示(包括菜单项和窗口):

using UnityEditor;
using UnityEngine;
using System.IO;
using System.Collections;
using System.Collections.Generic;

public class AssetBundleController : EditorWindow
{
    public static AssetBundleController window;
    public static UnityEditor.BuildTarget buildTarget = BuildTarget.StandaloneWindows;

    [MenuItem("XiYouEditor/AssetBundle/AssetBundle For Windows32", false, 1)]
    public static void ExecuteWindows32()
    {
        if (window == null)
        {
            window = (AssetBundleController)GetWindow(typeof(AssetBundleController));
        }
        buildTarget = UnityEditor.BuildTarget.StandaloneWindows;
        window.Show();
    }

    [MenuItem("XiYouEditor/AssetBundle/AssetBundle For IPhone", false, 2)]
    public static void ExecuteIPhone()
    {
        if (window == null)
        {
            window = (AssetBundleController)GetWindow(typeof(AssetBundleController));
        }
        buildTarget = UnityEditor.BuildTarget.iPhone;
        window.Show();
    }

    [MenuItem("XiYouEditor/AssetBundle/AssetBundle For Mac", false, 3)]
    public static void ExecuteMac()
    {
        if (window == null)
        {
            window = (AssetBundleController)GetWindow(typeof(AssetBundleController));
        }
        buildTarget = UnityEditor.BuildTarget.StandaloneOSXUniversal;
        window.Show();
    }

    [MenuItem("XiYouEditor/AssetBundle/AssetBundle For Android", false, 4)]
    public static void ExecuteAndroid()
    {
        if (window == null)
        {
            window = (AssetBundleController)GetWindow(typeof(AssetBundleController));
        }
        buildTarget = UnityEditor.BuildTarget.Android;
        window.Show();
    }

    [MenuItem("XiYouEditor/AssetBundle/AssetBundle For WebPlayer", false, 5)]
    public static void ExecuteWebPlayer()
    {
        if (window == null)
        {
            window = (AssetBundleController)GetWindow(typeof(AssetBundleController));
        }
        buildTarget = UnityEditor.BuildTarget.WebPlayer;
        window.Show();
    }

    void OnGUI()
    {
        if (GUI.Button(new Rect(10f, 10f, 200f, 50f), "(1)CreateAssetBundle"))
        {
            CreateAssetBundle.Execute(buildTarget);
            EditorUtility.DisplayDialog("", "Step (1) Completed", "OK");
        }

        if (GUI.Button(new Rect(10f, 80f, 200f, 50f), "(2)Generate MD5"))
        {
            CreateMD5List.Execute(buildTarget);
            EditorUtility.DisplayDialog("", "Step (2) Completed", "OK");
        }

        if (GUI.Button(new Rect(10f, 150f, 200f, 50f), "(3)Compare MD5"))
        {
            CampareMD5ToGenerateVersionNum.Execute(buildTarget);
            EditorUtility.DisplayDialog("", "Step (3) Completed", "OK");
        }

        if (GUI.Button(new Rect(10f, 220f, 200f, 50f), "(4)Build VersionNum.xml"))
        {
            CreateAssetBundleForXmlVersion.Execute(buildTarget);
            EditorUtility.DisplayDialog("", "Step (4) Completed", "OK");
        }
    }

    public static string GetPlatformPath(UnityEditor.BuildTarget target)
    {
        string SavePath = "";
        switch (target)
        {
            case BuildTarget.StandaloneWindows:
                SavePath = "Assets/AssetBundle/Windows32/";
                break;
            case BuildTarget.StandaloneWindows64:
                SavePath = "Assets/AssetBundle/Windows64/";
                break;
            case BuildTarget.iPhone:
                SavePath = "Assets/AssetBundle/IOS/";
                break;
            case BuildTarget.StandaloneOSXUniversal:
                SavePath = "Assets/AssetBundle/Mac/";
                break;
            case BuildTarget.Android:
                SavePath = "Assets/AssetBundle/Android/";
                break;
            case BuildTarget.WebPlayer:
                SavePath = "Assets/AssetBundle/WebPlayer/";
                break;
            default:
                SavePath = "Assets/AssetBundle/";
                break;
        }

        if (Directory.Exists(SavePath) == false)
            Directory.CreateDirectory(SavePath);

        return SavePath;
    }

    public static string GetPlatformName(UnityEditor.BuildTarget target)
    {
        string platform = "Windows32";
        switch (target)
        {
            case BuildTarget.StandaloneWindows:
                platform = "Windows32";
                break;
            case BuildTarget.StandaloneWindows64:
                platform = "Windows64";
                break;
            case BuildTarget.iPhone:
                platform = "IOS";
                break;
            case BuildTarget.StandaloneOSXUniversal:
                platform = "Mac";
                break;
            case BuildTarget.Android:
                platform = "Android";
                break;
            case BuildTarget.WebPlayer:
                platform = "WebPlayer";
                break;
            default:
                break;
        }
        return platform;
    }

}

(1)将资源打包成assetbundle,并放到自定目录下:

using UnityEditor;
using UnityEngine;
using System.IO;
using System.Collections;
using System.Collections.Generic;

public class CreateAssetBundle
{
    public static void Execute(UnityEditor.BuildTarget target)
    {
        string SavePath = AssetBundleController.GetPlatformPath(target);

        // 当前选中的资源列表
        foreach (Object o in Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets))
        {
            string path = AssetDatabase.GetAssetPath(o);

            // 过滤掉meta文件和文件夹
            if(path.Contains(".meta") || path.Contains(".") == false)
                continue;

            // 过滤掉UIAtlas目录下的贴图和材质(UI/Common目录下的所有资源都是UIAtlas)
            if (path.Contains("UI/Common"))
            {
                if ((o is Texture) || (o is Material))
                    continue;
            }

            path = SavePath + ConvertToAssetBundleName(path);
            path = path.Substring(0, path.LastIndexOf(‘.‘));
            path += ".assetbundle";

            BuildPipeline.BuildAssetBundle(o, null, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.DeterministicAssetBundle, target);
        }

        // scene目录下的资源

        AssetDatabase.Refresh();
    }

    static string ConvertToAssetBundleName(string ResName)
    {
        return ResName.Replace(‘/‘, ‘.‘);
    }

}

(2)为每个assetbund生成MD5码,用于检查资源是否有修改

using UnityEngine;
using UnityEditor;
using System.IO;
using System.Xml;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;

public class CreateMD5List
{
    public static void Execute(UnityEditor.BuildTarget target)
    {
        string platform = AssetBundleController.GetPlatformName(target);
        Execute(platform);
        AssetDatabase.Refresh();
    }

    public static void Execute(string platform)
    {
        Dictionary<string, string> DicFileMD5 = new Dictionary<string, string>();
        MD5CryptoServiceProvider md5Generator = new MD5CryptoServiceProvider();

        string dir = System.IO.Path.Combine(Application.dataPath, "AssetBundle/" + platform);
        foreach (string filePath in Directory.GetFiles(dir))
        {
            if (filePath.Contains(".meta") || filePath.Contains("VersionMD5") || filePath.Contains(".xml"))
                continue;

            FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            byte[] hash = md5Generator.ComputeHash(file);
            string strMD5 = System.BitConverter.ToString(hash);
            file.Close();

            string key = filePath.Substring(dir.Length + 1, filePath.Length - dir.Length - 1);

            if (DicFileMD5.ContainsKey(key) == false)
                DicFileMD5.Add(key, strMD5);
            else
                Debug.LogWarning("<Two File has the same name> name = " + filePath);
        }

        string savePath = System.IO.Path.Combine(Application.dataPath, "AssetBundle/") + platform + "/VersionNum";
        if (Directory.Exists(savePath) == false)
            Directory.CreateDirectory(savePath);

        // 删除前一版的old数据
        if (File.Exists(savePath + "/VersionMD5-old.xml"))
        {
            System.IO.File.Delete(savePath + "/VersionMD5-old.xml");
        }

        // 如果之前的版本存在,则将其名字改为VersionMD5-old.xml
        if (File.Exists(savePath + "/VersionMD5.xml"))
        {
            System.IO.File.Move(savePath + "/VersionMD5.xml", savePath + "/VersionMD5-old.xml");
        }

        XmlDocument XmlDoc = new XmlDocument();
        XmlElement XmlRoot = XmlDoc.CreateElement("Files");
        XmlDoc.AppendChild(XmlRoot);
        foreach (KeyValuePair<string, string> pair in DicFileMD5)
        {
            XmlElement xmlElem = XmlDoc.CreateElement("File");
            XmlRoot.AppendChild(xmlElem);

            xmlElem.SetAttribute("FileName", pair.Key);
            xmlElem.SetAttribute("MD5", pair.Value);
        }

        // 读取旧版本的MD5
        Dictionary<string, string> dicOldMD5 = ReadMD5File(savePath + "/VersionMD5-old.xml");
        // VersionMD5-old中有,而VersionMD5中没有的信息,手动添加到VersionMD5
        foreach (KeyValuePair<string, string> pair in dicOldMD5)
        {
            if (DicFileMD5.ContainsKey(pair.Key) == false)
                DicFileMD5.Add(pair.Key, pair.Value);
        }

        XmlDoc.Save(savePath + "/VersionMD5.xml");
        XmlDoc = null;
    }

    static Dictionary<string, string> ReadMD5File(string fileName)
    {
        Dictionary<string, string> DicMD5 = new Dictionary<string, string>();

        // 如果文件不存在,则直接返回
        if (System.IO.File.Exists(fileName) == false)
            return DicMD5;

        XmlDocument XmlDoc = new XmlDocument();
        XmlDoc.Load(fileName);
        XmlElement XmlRoot = XmlDoc.DocumentElement;

        foreach (XmlNode node in XmlRoot.ChildNodes)
        {
            if ((node is XmlElement) == false)
                continue;

            string file = (node as XmlElement).GetAttribute("FileName");
            string md5 = (node as XmlElement).GetAttribute("MD5");

            if (DicMD5.ContainsKey(file) == false)
            {
                DicMD5.Add(file, md5);
            }
        }

        XmlRoot = null;
        XmlDoc = null;

        return DicMD5;
    }

}

MD5列表如下所示:

<Files>
  <File FileName="Assets.Resources.BigLevelTexture.TestLevel.assetbundle" MD5="54-00-42-38-D5-86-43-A6-57-9D-7C-09-3A-F8-6E-10" />
  <File FileName="Assets.Resources.EquipmentTexture.Test001.assetbundle" MD5="A1-19-D4-04-17-94-18-61-60-99-35-25-3F-7C-39-93" />
  <File FileName="Assets.Resources.EquipmentTexture.Test002.assetbundle" MD5="CF-36-DA-C8-D2-DB-CE-FD-4A-BF-31-81-A1-D1-D2-21" />
  <File FileName="Assets.Resources.EquipmentTexture.Test003.assetbundle" MD5="EF-30-78-AE-F8-F4-A0-EC-5B-4E-45-3F-1E-EF-42-44" />
  <File FileName="Assets.Resources.EquipmentTexture.Test004.assetbundle" MD5="3D-5D-A7-01-D2-B1-20-5F-B9-89-C5-CB-40-96-EC-89" />
  <File FileName="Assets.Resources.PetTexture.Empty.assetbundle" MD5="D9-AC-54-F8-EB-AA-1C-36-8C-2B-6C-12-37-AB-3B-48" />
</Files>

(3)比较新旧MD5码,生成资源变更列表

using UnityEngine;
using UnityEditor;
using System.IO;
using System.Xml;
using System.Collections;
using System.Collections.Generic;

public class CampareMD5ToGenerateVersionNum
{
    public static void Execute(UnityEditor.BuildTarget target)
    {
        string platform = AssetBundleController.GetPlatformName(target);
        Execute(platform);
        AssetDatabase.Refresh();
    }

    // 对比对应版本目录下的VersionMD5和VersionMD5-old,得到最新的版本号文件VersionNum.xml
    public static void Execute(string platform)
    {
        // 读取新旧MD5列表
        string newVersionMD5 = System.IO.Path.Combine(Application.dataPath, "AssetBundle/" + platform + "/VersionNum/VersionMD5.xml");
        string oldVersionMD5 = System.IO.Path.Combine(Application.dataPath, "AssetBundle/" + platform + "/VersionNum/VersionMD5-old.xml");

        Dictionary<string, string> dicNewMD5Info = ReadMD5File(newVersionMD5);
        Dictionary<string, string> dicOldMD5Info = ReadMD5File(oldVersionMD5);

        // 读取版本号记录文件VersinNum.xml
        string oldVersionNum = System.IO.Path.Combine(Application.dataPath, "AssetBundle/" + platform + "/VersionNum/VersionNum.xml");
        Dictionary<string, int> dicVersionNumInfo = ReadVersionNumFile(oldVersionNum);

        // 对比新旧MD5信息,并更新版本号,即对比dicNewMD5Info&&dicOldMD5Info来更新dicVersionNumInfo
        foreach (KeyValuePair<string, string> newPair in dicNewMD5Info)
        {
            // 旧版本中有
            if (dicOldMD5Info.ContainsKey(newPair.Key))
            {
                // MD5一样,则不变
                // MD5不一样,则+1
                // 容错:如果新旧MD5都有,但是还没有版本号记录的,则直接添加新纪录,并且将版本号设为1
                if (dicVersionNumInfo.ContainsKey(newPair.Key) == false)
                {
                    dicVersionNumInfo.Add(newPair.Key, 1);
                }
                else if (newPair.Value != dicOldMD5Info[newPair.Key])
                {
                    int num = dicVersionNumInfo[newPair.Key];
                    dicVersionNumInfo[newPair.Key] = num + 1;
                }
            }
            else // 旧版本中没有,则添加新纪录,并=1
            {
                dicVersionNumInfo.Add(newPair.Key, 1);
            }
        }
        // 不可能出现旧版本中有,而新版本中没有的情况,原因见生成MD5List的处理逻辑

        // 存储最新的VersionNum.xml
        SaveVersionNumFile(dicVersionNumInfo, oldVersionNum);
    }

    static Dictionary<string, string> ReadMD5File(string fileName)
    {
        Dictionary<string, string> DicMD5 = new Dictionary<string, string>();

        // 如果文件不存在,则直接返回
        if (System.IO.File.Exists(fileName) == false)
            return DicMD5;

        XmlDocument XmlDoc = new XmlDocument();
        XmlDoc.Load(fileName);
        XmlElement XmlRoot = XmlDoc.DocumentElement;

        foreach (XmlNode node in XmlRoot.ChildNodes)
        {
            if ((node is XmlElement) == false)
                continue;

            string file = (node as XmlElement).GetAttribute("FileName");
            string md5 = (node as XmlElement).GetAttribute("MD5");

            if (DicMD5.ContainsKey(file) == false)
            {
                DicMD5.Add(file, md5);
            }
        }

        XmlRoot = null;
        XmlDoc = null;

        return DicMD5;
    }

    static Dictionary<string, int> ReadVersionNumFile(string fileName)
    {
        Dictionary<string, int> DicVersionNum = new Dictionary<string, int>();

        // 如果文件不存在,则直接返回
        if (System.IO.File.Exists(fileName) == false)
            return DicVersionNum;

        XmlDocument XmlDoc = new XmlDocument();
        XmlDoc.Load(fileName);
        XmlElement XmlRoot = XmlDoc.DocumentElement;

        foreach (XmlNode node in XmlRoot.ChildNodes)
        {
            if ((node is XmlElement) == false)
                continue;

            string file = (node as XmlElement).GetAttribute("FileName");
            int num = XmlConvert.ToInt32((node as XmlElement).GetAttribute("Num"));

            if (DicVersionNum.ContainsKey(file) == false)
            {
                DicVersionNum.Add(file, num);
            }
        }

        XmlRoot = null;
        XmlDoc = null;

        return DicVersionNum;
    }

    static void SaveVersionNumFile(Dictionary<string, int> data, string savePath)
    {
        XmlDocument XmlDoc = new XmlDocument();
        XmlElement XmlRoot = XmlDoc.CreateElement("VersionNum");
        XmlDoc.AppendChild(XmlRoot);

        foreach (KeyValuePair<string, int> pair in data)
        {
            XmlElement xmlElem = XmlDoc.CreateElement("File");
            XmlRoot.AppendChild(xmlElem);
            xmlElem.SetAttribute("FileName", pair.Key);
            xmlElem.SetAttribute("Num", XmlConvert.ToString(pair.Value));
        }

        XmlDoc.Save(savePath);
        XmlRoot = null;
        XmlDoc = null;
    }

}

如下图所示,根据VersionMD5.xml和VersionMD5-old.xml对比产生VersionNum.xml:

(4)将变更列表文件也打包成assetbundle

也就是讲VersionNum.xml打包后供下载:

using UnityEditor;
using UnityEngine;
using System.IO;
using System.Collections;
using System.Collections.Generic;

public class CreateAssetBundleForXmlVersion
{
    public static void Execute(UnityEditor.BuildTarget target)
    {
        string SavePath = AssetBundleController.GetPlatformPath(target);
        Object obj = AssetDatabase.LoadAssetAtPath(SavePath + "VersionNum/VersionNum.xml", typeof(Object));
        BuildPipeline.BuildAssetBundle(obj, null, SavePath + "VersionNum/VersionNum.assetbundle", BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.DeterministicAssetBundle, target);

        AssetDatabase.Refresh();
    }

    static string ConvertToAssetBundleName(string ResName)
    {
        return ResName.Replace(‘/‘, ‘.‘);
    }

}
时间: 2024-10-17 21:55:32

[Unity Asset]AssetBundle系列——游戏资源打包的相关文章

Unity3d 游戏资源打包加密(图片/XML/TXT等) C#编码 (一)

本文只是讲述一下过程,采用很简单的打包加密方法,至于需要什么样的加密结果,请大家按照需求去修改,字节偏移.前后颠倒加算法都可以,不过一般无需这么复杂,而且太复杂的加密对于极其追求运行效率的游戏来说,也是一重负担. 对于Unity,虽然Unity自身会进行压缩加密,但是其解密算法在网上随处可见,如果自己觉得游戏里面的资料具有保密性质,请对其进行自行加密. 打包加密的原理: 1.大家都知道文件都是由字节组成的. 2.一张图片之所以看起来很漂亮,是因为其数据按照一定顺序排列. 漂亮的剑灵妹子 我们可以

Cocos2d-x 游戏资源(图片、XML、TXT等)打包加密 之 解密读取

自上一篇  Unity3d 游戏资源打包加密(图片/XML/TXT等) C#编码 (一)   介绍如何打包加密游戏资源已经好几月,却没有详细说明如何在游戏中去读取加密的资源,虽然聪明的程序员看一眼就知道如何逆向编码,但是还是详细说明一下,以作完结. 转自陈里陈外的博客 http://blog.csdn.net/huutu 星环游戏 http://www.thisisgame.com.cn Cocos2d-X 资源加密与解密 加密只有一篇即可,解密分为两篇,Cocos2d-x 篇 和 Unity3

Unity3D游戏开发之使用disunity提取Unity3D游戏资源

各位朋友,大家好,我是秦元培.今天博主想和分享的是使用disunity提取Unity3D游戏素材.这个工具呢,博主在Unity3D游戏开发之反编译AssetBundle提取游戏资源这篇文章中其实已经提到过了,不过因为有些朋友对如何使用这个工具依然存在问题,所以博主决定特地写一篇文章来讲解如何使用disunity来提取Unity3D游戏中的素材. 准备工作 disunity:负责对Unity3D的数据文件进行解包 Unity3D:负责将导出的数据文件显示出来 Bleander或者3DsMax:负责

【Cocos2d-Js基础教学(5)资源打包工具的使用及资源的异步加载处理】

[转载]http://www.cnblogs.com/zisou/p/cocos2dx-js5.html   TexturePacker是纹理资源打包工具,支持Cocos2dx的游戏资源打包. 如果用过的同学可以直接看下面的资源的异步加载处理 首先为什么用TexturePacker? 1,节省图片资源实际大小 2,减少我们游戏中大量资源带来的内存负荷 3,方便游戏对纹理资源的内存管理 游戏开发到后期,我们或许都会遇到的瓶颈就是需要对游戏包进行"瘦身"和内存优化.那么使用TextureP

Unity资源打包之Assetbundle

转  Unity资源打包之Assetbundle 本文原创版权归 csdn janeky 所有,转载请详细注明原创作者及出处,以示尊重! 作者:janeky 原文:http://blog.csdn.net/janeky/article/details/17652021 如果这篇文章对你有帮助,敬请关注作者<Unity手游之路>系列教程. 在手游的运营过程中,更新资源是比不可少的.资源管理第一步是资源打包.传统的打包可以将所有物件制成预设Prefab,打包成场景.今天我们来一起学习官方推荐的As

Unity手游之路&lt;十一&gt;资源打包Assetbundle

http://blog.csdn.net/janeky/article/details/17652021 在手游的运营过程中,更新资源是比不可少的.资源管理第一步是资源打包.传统的打包可以将所有物件制成预设Prefab,打包成场景.今天我们来一起学习官方推荐的Assetbundle,它是Unity(Pro)提供的资源打包策略.利用AssetBundle,可以将几乎所有的资源都打包封装,便于客户端更新下载新的资源. (转载请注明原文出处http://blog.csdn.net/janeky/art

Unity 浅谈AssetBundle 游戏资源

--刚刚做完一个xlua的的热更项目,对AssetBundle资源分类总结一下.纯理论,闲谈知识,要是有建议,尽管提 ,不掺杂代码. --这里说说,AB是如何打包,如果下载,如何加载. 关键词理解:依赖,被依赖,公共, 非公共,. 1.如何打包? 游戏资源的话,我这里是分为两大类. 常驻资源 I.常驻公共资源(主界面图集,背景音乐等的必须要加载的资源) ||.非 常驻公共资源(战斗界面图集,因为存在只登录游戏,不进战斗的情况) 非常驻资源 |||.经常反复资源 V.其他 2.下载资源? 下载资源

还在用难用的AssetBundle?快来运用Unity新的可寻址资源系统,助力游戏开发

Unity Addressables可寻址资源系统是一个强大的Unity资源包,它能够帮助解决游戏开发中最重要的一些挑战:高效率和轻松的内容管理. 在管理游戏资源时,往往很难维持好的标准,从而避免让项目变得杂乱无章.最主要的问题在于不同职责的资源管理系统之间的耦合.而且,项目中资源的存储,加载和载入后资源的使用方法都有紧密的联系. 例如:我们可能要在Resources文件夹存储某个精灵.这会让Unity在构建版本时,把精灵存到特定的存档文件中.由于精灵存在了这样的位置,我们必须通过Resourc

资源打包Assetbundle .

在手游的运营过程中,更新资源是比不可少的.资源管理第一步是资源打包.传统的打包可以将所有物件制成预设Prefab,打包成场景.今天我们来一起学习官方推荐的Assetbundle,它是Unity(Pro)提供的资源打包策略.利用AssetBundle,可以将几乎所有的资源都打包封装,便于客户端更新下载新的资源. (转载请注明原文出处http://blog.csdn.net/janeky/article/details/17652021) 创建AssetBundle 1.创建一个空的Prefab,命