AssetBundle系列——游戏资源打包(二)

本篇接着上一篇。上篇中说到的4步的代码分别如下所示:

(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:

AssetBundle系列——游戏资源打包(二)

(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('/', '.');

    }
}

 

你可能感兴趣的:(Bundle)