添加Verison写入方法

我们在BuildApp中添加新的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
static void SaveVersion(string version,string package)
{
string content = "Version|" + version + ";PackageName|" + package + ";";
string savePath = Application.dataPath + "/Resources/Version.txt";
string lineOne = "";
string all = "";
using(FileStream fs = new FileStream(savePath, FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite))
{
using(StreamReader sr = new StreamReader(fs,System.Text.Encoding.UTF8))
{
all = sr.ReadToEnd();
lineOne = all.Split('\r')[0];//这样写防止文件没有换行符读取不到第一行
}
}
//先读取再写入是因为我们的Version.txt在第一行下面可能会有其他内容,我们需要保留着
using(FileStream fs = new FileStream(savePath, FileMode.OpenOrCreate))
{
using (StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8))
{
if(string.IsNullOrEmpty(all))
{
all = content;
}
else
{
all = all.Replace(lineOne, content);
}
sw.Write(all);
}
}
}

使用这个方法后,工程内的Resource文件夹下就会有Version.txt文件

1
Version|0.1;PackageName|com.DefaultCompany.ResLoadPrg;

这个文件可能会包含更多信息,比如服务器和端口号,不同平台的包名解释等等。所以在方法中我们先读取此文件,再写入。

BuildAppBuild方法中调用此方法

1
2
3
4
5
6
7
8
9
[MenuItem("Build/标准包")]
public static void Build()
{
//打AB包
BundleEditor.Build();
SaveVersion(PlayerSettings.bundleVersion, PlayerSettings.applicationIdentifier);//+++
//...
}

资源信息类

资源信息类用于记录所有的ab包的包名、MD5码和Size。用于比较生成热更包。

在工程文件夹下的ResFrame——Frames——ResourceFrm——Download文件夹下新建ABMD5脚本文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System.Collections.Generic;
using System.Xml.Serialization;

[System.Serializable]
public class ABMD5
{
[XmlElement("ABMD5List")]
public List<ABMD5Base> ABMD5List { get; set; }
}
[System.Serializable]
public class ABMD5Base
{
[XmlAttribute("Name")]
public string Name { get; set; }
[XmlAttribute("MD5")]
public string MD5 { get; set; }
[XmlAttribute("Size")]
public float Size { get; set; }
}

MD5码生成

在工程文件夹下的ResFrame——Frames——ResourceFrm下新建MD5Manager脚本文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using UnityEngine;
using System;
using System.Security.Cryptography;
using System.IO;
using System.Text;

[Serializable]
public class MD5Manager : SingletonPattern<MD5Manager>
{
/// <summary>
/// 储存MD5码
/// </summary>
/// <param name="filePath">文件路径</param>
/// <param name="md5SavePath">MD5码储存路径</param>
public void SaveMD5(string filePath, string md5SavePath)
{
string md5 = BuildFileMD5(filePath);
string name = md5SavePath + "_md5.dat";
if(File.Exists(name))
{
File.Delete(name);
}
StreamWriter sw = new StreamWriter(name,false, Encoding.UTF8);
if(sw!=null)
{
sw.Write(md5);
sw.Flush();
sw.Close();
}
}
/// <summary>
/// 储存MD5码,生成的MD5码储存在同一路径下
/// </summary>
/// <param name="filePath">文件路径</param>
public void SaveMD5(string filePath)
{
string md5 = BuildFileMD5(filePath);
string name = filePath + "_md5.dat";
if (File.Exists(name))
{
File.Delete(name);
}
StreamWriter sw = new StreamWriter(name, false, Encoding.UTF8);
if (sw != null)
{
sw.Write(md5);
sw.Flush();
sw.Close();
}
}
/// <summary>
/// 获取之前储存的MD5码
/// </summary>
/// <param name="filePath">文件路径</param>
/// <returns>MD5</returns>
public string GetMD5(string filePath)
{
string md5Name = filePath + "_md5.dat";
try
{
StreamReader sr = new StreamReader(md5Name, Encoding.UTF8);
string content = sr.ReadToEnd();
sr.Close();
return content;
}
catch (Exception)
{

return string.Empty;
}
}
/// <summary>
/// 生成文件的MD5码
/// </summary>
/// <param name="filePath">文件路径</param>
/// <returns>MD5</returns>
public string BuildFileMD5(string filePath)
{
string fileMD5 = null;
try
{
using (FileStream fs = File.OpenRead(filePath))
{
MD5 md5 = MD5.Create();
byte[] fileMD5Bytes = md5.ComputeHash(fs);
fileMD5 = FormatMD5(fileMD5Bytes);
}
}
catch (Exception e)
{
Debug.LogError(e);
}
return fileMD5;
}
/// <summary>
/// 将字节数组转换成字符串
/// </summary>
/// <param name="data">字节数组</param>
/// <returns>字节字符串</returns>
string FormatMD5(byte[] data)
{
return System.BitConverter.ToString(data, 0, data.Length).Replace("-","").ToLower();
}
}

添加信息写入方法

AB包的信息是需要在打AB包的时候生成的,我们给BundleEditor添加WriteABMD5方法,并在Build方法里,AssetBundle生成修改完成时调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
   public static void Build()
{
//...
for (int i = 0; i < oldNames.Length; i++)
{
AssetDatabase.RemoveAssetBundleName(oldNames[i], true);
EditorUtility.DisplayProgressBar("清除AB包名", "名字:" + oldNames[i],i*1.0f/oldNames.Length);
}
WriteABMD5();//+++
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.ClearProgressBar();

}

/// <summary>
/// 根据已经生成的AssetBundle,收集整理它们的文件信息
/// </summary>
static void WriteABMD5()
{
DirectoryInfo directoryInfo = new DirectoryInfo(m_BundleTargetPath);
FileInfo[] fileInfos = directoryInfo.GetFiles("*",SearchOption.AllDirectories);
ABMD5 aBMD5 = new ABMD5();
aBMD5.ABMD5List = new List<ABMD5Base>();
for (int i = 0; i < fileInfos.Length; i++)
{
if (!fileInfos[i].Name.EndsWith(".meta") && !fileInfos[i].Name.EndsWith(".manifest"))
{
ABMD5Base aBMD5Base = new ABMD5Base();
aBMD5Base.Name = fileInfos[i].Name;
aBMD5Base.MD5 = MD5Manager.Instance.BuildFileMD5(fileInfos[i].FullName);
aBMD5Base.Size = fileInfos[i].Length / 1024.0f;//从bit转为kb
aBMD5.ABMD5List.Add(aBMD5Base);
}
}
string ABMD5Path = Application.dataPath + "/Resources/ABMD5.bytes";
BinarySerializeOpt.BinarySerialize(ABMD5Path, aBMD5);
}

储存不同版本不同平台的ABMD5信息

经过上面的操作,每次打包的ABMD5信息都会储存在Resources文件夹内,但是每次打包,ABMD5信息都会被覆盖。我们需要把每次在不同的平台不同版本的ABMD5信息都给储存下来。从而能够比较文件更新的信息,筛选出真正需要更新的包。

在Unity工程文件夹(Assets的父文件夹)内新建Version文件夹。

注意要将Version文件夹上传SVN。

修改BundleEditor脚本,首先添加m_VersionMD5Path

1
2
3
4
5
public class BundleEditor 
{
//...
private static string m_VersionMD5Path = Application.dataPath + "/../Version/" + EditorUserBuildSettings.activeBuildTarget.ToString();
}

然后修改WriteABMD5方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static void WriteABMD5()
{
//...
string ABMD5Path = Application.dataPath + "/Resources/ABMD5.bytes";
BinarySerializeOpt.BinarySerialize(ABMD5Path, aBMD5);
//将文件MD5拷贝到外部进行储存
if (!Directory.Exists(m_VersionMD5Path))
{
Directory.CreateDirectory(m_VersionMD5Path);
}
string targetPath = m_VersionMD5Path + "/ABMD5_" + PlayerSettings.bundleVersion + ".bytes";//Version\平台文件夹\ABMD5_版本号.bytes
if (File.Exists(targetPath))
{
File.Delete(targetPath);
}
File.Copy(ABMD5Path, targetPath);
}