您的位置:首页 > 移动开发 > Unity3D

Unity热更新系列之AssetBundle(3) ——资源文件 xml 清单的生成与读取

2018-04-03 16:51 956 查看
当我们想要进行游戏资源热更新时,需要知道哪些资源文件需要进行热更新,

而最常见的做法就是使用一个文件记录每一个资源文件的version信息。

在玩家每次登陆游戏时,获取资源服务器上的version文件,

将其与本地文件进行对比,从而筛选出需要热更新的资源进行下载。

这里我们使用 xml 格式的文件用来处理这些信息。

我这里设计的version文件结构如下,首先是版本号,可以用来获取玩家当前的资源版本号。

接下来是一系列的资源信息列表 ,其中

name:该资源的 AssetBundle name,用来拼接该资源的下载路径(url = 资源服务器地址 + name )。

size : 该文件字节数,用来热更新时统计所需更新资源的大小。

md5码 : 用来比对该资源是否发生过更改,如果同一个资源的 md5码 本地和服务器不一致

,则证明需要下载该资源,将其加入到热更新下载队列。



这个文件当然不可能每次都自己手动生成,这里提供一下生成该version.xml文件的代码和读取方式

生成:

/// <summary>
/// 生成version.xml文件
/// </summary>
/// <param name="xmlPaths"></param>
///
[MenuItem("Build/生成verison.xml")]
public static void CreateVersionXml()
{
string outputPath = Application.dataPath.Replace("Assets","") + "Android";

//xml声明
XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateXmlDeclaration("1.0", "UTF-8", null));
//生成根节点
xml.AppendChild(xml.CreateElement("Root"));
//生成大版本号
XmlNode root = xml.SelectSingleNode("Root");
XmlElement verNode = xml.CreateElement("version");

//版本号这里写死,如有需要,自由赋值
verNode.InnerText = "2.0";

root.AppendChild(verNode);
//创建res节点
XmlElement resNode = xml.CreateElement("res");
root.AppendChild(resNode);
//选择所有需要打包的资源类型
string[] files = System.IO.Directory.GetFiles(outputPath, "*.*", SearchOption.AllDirectories).Where(t => (t.EndsWith(".unity3d"))).ToArray();

//为每一个文件生成相应的xml
foreach (var file in files)
{
FileInfo fileInfo = new FileInfo(file);
string name = fileInfo.FullName.Replace("\\", "/").Replace(outputPath + "/", "");
AddNodeToXML(xml, name, MD5File(file), fileInfo.Length);
}

//将xml文件写入res目录下
xml.Save(outputPath + @"/version.xml");

System.Diagnostics.Process.Start(outputPath, outputPath);
}
/// <summary>
/// 计算md5码
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
private static string MD5File(string file)
{
try
{
FileStream fs = new FileStream(file, FileMode.Open);
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(fs);
fs.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
catch (System.Exception ex)
{
throw new System.Exception("md5file() fail, error:" + ex.Message);
}
}
/// <summary>
/// 添加节点
/// </summary>
/// <param name="xml"></param>
/// <param name="name"></param>
/// <param name="md5Str"></param>
/// <param name="length"></param>
private static void AddNodeToXML(XmlDocument xml, string name, string md5Str, long size)
{
//获取根节点
XmlNode resNode = xml.SelectSingleNode("Root/res");
//添加元素
XmlElement element = xml.CreateElement("res");
element.SetAttribute("name", name);
element.SetAttribute("size", size.ToString());
element.InnerText = md5Str;
resNode.AppendChild(element);
}


这里我们在Assets同层级文件夹目录下操作,这是因为如果在 Assets路径下进行文件增加删除操作,

会触发Unity 的AssetDatabase 的刷新,重新加载这些新生成的文件,并生成 .meta文件。



我们在这里新建了一个资源文件夹,存放Android平台的有戏资源,

并在里面放置了若干图集资源的AssetBundle文件。



然后运行代码,生成相应的version.xml 。

加载就相对简单的多了,我们只需要将xml的文件结构通过一个类映射出来,

再使用XmlSerializer.Deserialize() 解析就好了。

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

public class xmlload : MonoBehaviour {

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.D))
{
string localversionPath = "file:///" + Application.dataPath.Replace("Assets", "") + "Android" + "/version.xml";
StartCoroutine(IELoadVersion(localversionPath));
}
}

public IEnumerator IELoadVersion(string path) {
WWW www = new WWW(path);
while (!www.isDone)
{
yield return null;
}
Stream stream = new MemoryStream(www.bytes);
XmlSerializer xmlser = new XmlSerializer(typeof(CVersion));
CVersion localVersion = (CVersion)xmlser.Deserialize(stream);
stream.Close();
www.Dispose();

foreach (var item in localVersion.element)
{
Debug.Log(item.name + " " + item.size + "   " + item.md5);
}
}
}

/// <summary>
/// version.xml的结构映射类
/// </summary>
[XmlRoot("Root")]
public class CVersion
{
[XmlElement("version")]
public string version;
[XmlArray("res"), XmlArrayItem("res")]
public List<Version> element = new List<Version>();
}
[XmlRoot("res")]
public class Version
{
[XmlAttribute("name")]
public string name;
[XmlAttribute("size")]
public string size;
[XmlText()]
public string md5;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unity 游戏 xml
相关文章推荐