[Unity Asset] Assetbundle Series--Game resource packaging

Source: Internet
Author: User

Reprint: http://www.cnblogs.com/sifenkesi/p/3557231.html

Package The local resources and place them on the resource server to download or update the game client. The following list of resources is included on the server:
(1) Game content Resources Assetbundle
(2) Resource maintenance list containing the name of each resource (full path name) and the corresponding version number [resource name, version number]as shown in the following table (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>

Then the resource packaging editor for the local client needs to do the following: Package the resource, build the version number.
We use the MD5 code to manage the version number, if the MD5 code of a resource changed, then its version number +1, otherwise unchanged. Then, the specific tasks of the editor can be divided as follows:
(1) Package the resources into assetbundle and place them in the specified directory
(2) generate the latest MD5 code for each assetbund to check if the resource has been modified
(3) Compare the new and old MD5 code list, generate a list of resource changes, for each changed resource, its version number +1
(4) Package The change list file as Assetbundle

The resource bundles used by each platform are separate, the options for packaging resource codes are different, the editor interface is as follows, and each of the 4 buttons in Figure 2 corresponds to one of these steps:

The resulting resource directory structure is as follows:

The editor code looks like the following (including menu items and Windows):

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 (build            Target);        Editorutility.displaydialog ("", "Step (3) completed", "OK"); } if (GUI. button (new Rect (10f, 220f, 200f, 50f), "(4) Build versionnum.xml")) {Createassetbundleforxmlversion.exec            Ute (Buildtarget);        Editorutility.displaydialog ("", "Step (4) completed", "OK");        }} public static string Getplatformpath (Unityeditor.buildtarget target) {string savepath = ""; SWitch (target) {case BuildTarget.StandaloneWindows:SavePath = "Assets/assetbundle/windo                ws32/";            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) package the resource into assetbundle and place it in a custom directory:

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);            Currently selected Resource list foreach (Object o in Selection.getfiltered (typeof (Object), Selectionmode.deepassets)) {            String path = Assetdatabase.getassetpath (o); Filter out meta files and folders if (path. Contains (". Meta") | | Path.            Contains (".") = = false) continue; Filter out the maps and textures under the Uiatlas directory (all resources under the Ui/common directory are 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 directory for resource Assetdatabase.refresh ();    } static string Converttoassetbundlename (String resname) {return resname.replace ('/', '. '); }}

(2) generates a MD5 code for each assetbund to check for changes to the resource

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&        Lt;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.contai NS ("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); Delete the previous version of the old data if (file.exists (Savepath + "/versionmd5-old.xml")) {System.IO.File.Delete (Savepat        H + "/versionmd5-old.xml");            }//If the previous version is present, change its name to 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.createelem            ENT ("File");            Xmlroot.appendchild (Xmlelem); Xmlelem.setattribute ("FileName", pair.            Key); Xmlelem.setattribute ("MD5", pair.        Value);        }//Read the old version of MD5 dictionary<string, string> dicOldMD5 = readmd5file (Savepath + "/versionmd5-old.xml"); Versionmd5-old there is, and VersionMD5 does not have information that is manually added to VersionMD5 foreach (keyvaluepair<string, string> pair in di COLDMD5) {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 the file does not exist, return directly 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) Continu            E 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; }}

The MD5 list is as follows:

<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) Compare the old and new MD5 code, generate a list of resource changes

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 ();        }//Compare the corresponding version directory with VersionMD5 and Versionmd5-old to get the latest version number file Versionnum.xml public static void Execute (String platform) { Read the new old MD5 list 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); Read version number record file Versinnum.xml stringOldversionnum = System.IO.Path.Combine (Application.datapath, "assetbundle/" + platform + "/versionnum/versionnum.xml"        );        dictionary<string, int> dicversionnuminfo = Readversionnumfile (oldversionnum); Compare the old and new MD5 information and update the version number, that is, compare Dicnewmd5info&&dicoldmd5info to update dicversionnuminfo foreach (keyvaluepair<string, S            Tring> Newpair in Dicnewmd5info) {//old version with if (Dicoldmd5info.containskey (Newpair.key)) {//MD5 same, then//MD5 is not the same, then +1//Fault tolerance: If the old and new MD5 have, but there is no version number recorded, then directly add a record, and Set the version number to 1 if (Dicversionnuminfo.containskey (newpair.key) = = False) {Dicver                Sionnuminfo.add (Newpair.key, 1); } else if (newpair.value! = Dicoldmd5info[newpair.key]) {int num = Dicve                    Rsionnuminfo[newpair.key];                Dicversionnuminfo[newpair.key] = num + 1;       }            }     else//Not in the previous version, add a new record and =1 {Dicversionnuminfo.add (Newpair.key, 1); }}//Can not appear in the old version, but not in the new version of the situation, the reason is the processing logic of generating md5list//storage of the latest Versionnum.xml Saveversionnumfile (dicve    Rsionnuminfo, Oldversionnum); } static dictionary<string, string> readmd5file (string fileName) {dictionary<string, string> Dic        MD5 = new dictionary<string, string> ();        If the file does not exist, return directly 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) Continu            E 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> Di        Cversionnum = new dictionary<string, int> ();        If the file does not exist, return directly 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) Continu            E 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; }}

As shown, the Versionnum.xml is produced according to Versionmd5.xml and Versionmd5-old.xml comparisons:

(4) Package The change list file as Assetbundle

That is to say versionnum.xml after packing for download:

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

[Unity Asset] Assetbundle Series--Game resource packaging

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.