【Unity】AB包下载
1.使用插件打AB包
a.AB包分类
一般地,将预制体作为AB包资源,不仅需要对预制体本身进行归类,还要对其涉及的动画(AnimationClip)、动画状态机(AnimatorController)、以及所用到的骨骼(Avatar)、模型(Mesh)、模型所用的材质(Matreial)、材质所用的图片(Images)、Shader等进行归类。
还有一种是AB包依赖情况,后面接触会在这里补充。
归类的资源对象名字是自定义,这里写XXX.unity3d,是为了在项目中处理。最后打包出来的就是这个名字的AB包,不过从AB包加载出来具体预制体时,就是当前打包时改预制体的原名。例如是存放在XXX.unity3d的AB包中的名字为 Cube 预制体。
b.使用官方打包工具 AssetBundles-Browser-master
压缩对象的设置及输出文件
2.创建AB包对比文件
AB包对比文件的作用:
- 判断本地是否存在AB包,有就不需要从服务器下载
- 判断本地AB包是否最新,不是则需要从服务器下载
递归查找文件夹中所有文件信息
/// <summary>
/// 获取文件信息
/// </summary>
/// <param name="target">根目录文件</param>
/// <returns>该目录所有文件信息,包括子文件夹中的</returns>
private List<FileInfo> GetFoldersInfo(string target)
{
int length = 0;
List<FileInfo> fileInfolist = new List<FileInfo>();
//获取文件夹下所有文件
DirectoryInfo directory = Directory.CreateDirectory(target);
FileInfo[] fileInfos = directory.GetFiles();
length = fileInfos.Length;
for (int i = 0; i < length; i++)
{
fileInfolist.Add(fileInfos[i]);
}
//获取文件夹下所有文件夹
string[] folders = Directory.GetDirectories(target);
length = folders.Length;
for (int i = 0; i < length; i++)
{
//获取子文件夹中所有文件
List<FileInfo> lst = GetFoldersInfo(folders[i]);
int len = lst.Count;
for (int j = 0; j < len; j++)
{
fileInfolist.Add(lst[j]);
}
}
return fileInfolist;
}
获取某个文件的MD5码
/// <summary>
/// 获取MD5码
/// </summary>
/// <param name="filePath">文件路径</param>
/// <returns>该文件的MD5码</returns>
private string GetFileMD5(string filePath)
{
//打开文件
using (FileStream file = new FileStream(filePath, FileMode.Open))
{
//使用MD5格式
MD5 md5 = new MD5CryptoServiceProvider();
//获取文件MD码
byte[] data = md5.ComputeHash(file);
//关闭文件
file.Close();
//释放占用资源
file.Dispose();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
//将数据转化成小写的16进制
sb.Append(data[i].ToString("x2"));
}
return sb.ToString();
}
}
创建AB包对比文件信息
/// <summary>
/// 创建AB包对比文件
/// </summary>
private void CreateABCompareFile()
{
文件夹信息
//DirectoryInfo directory = Directory.CreateDirectory(Application.dataPath + "/ABResource/AB/" + platformStr[platformIdx]);
获取文件夹中所有文件
//FileInfo[] fileInfos = directory.GetFiles();
//获取路径中所有的文件信息 platformStr[platformIdx]为生成AB包的路劲 例如:platformStr[platformIdx] == "Android"
List<FileInfo> fileInfos = GetFoldersInfo(Application.dataPath + "/ABResource/AB/" + platformStr[platformIdx]);
//声明字符串用来存储AB对比数据
string abCompareInfo = string.Empty;
int index = -1;
string localPath = "";
foreach (FileInfo fileInfo in fileInfos)
{
//没有扩展名的就是AB包,这里只是客观的进行判断,具体看打出来的AB包规则
//AB包保存的目录也会生成一个文件
if (fileInfo.Extension == "" && fileInfo.Name != platformStr[platformIdx])
{
//存储 AB包名字 字节长度 MD5码 用空格隔开,用"|"隔开每个文件信息
//收集相对路劲
index = fileInfo.FullName.LastIndexOf(platformStr[platformIdx]);
if(index == -1)
{
continue;
}
localPath = fileInfo.FullName.Substring(index + platformStr[platformIdx].Length + 1);
localPath = localPath.Replace("\\", "/");
//abCompareInfo += fileInfo.Name + " " + fileInfo.Length + " " + GetFileMD5(fileInfo.FullName);
//存储成字符串
abCompareInfo += localPath + " " + fileInfo.Length + " " + GetFileMD5(fileInfo.FullName);
abCompareInfo += "|";
}
}
//去除最后一个“|”字符
abCompareInfo = abCompareInfo.Substring(0, abCompareInfo.Length - 1);
//创建 ABCompareInfo.txt 文件作为AB包对比信息文件
File.WriteAllText(Application.dataPath + "/ABResource/AB/" + platformStr[platformIdx] + "/ABCompareInfo.txt", abCompareInfo);
//刷新Unity资源目录
AssetDatabase.Refresh();
Debug.Log("[" + platformStr[platformIdx] + "]生成AB包对比文件成功");
}
调用CreateABCompareFile()后,就会在对应的文件目录下生成AB包对比文件,接着将对比文件和AB包文件上传到服务器。
3.从服务器下载文件并保存本地
//服务器路劲
private static string serverPath = "http://127.0.0.1:8800/Game/";
/// <summary>
/// 下载文件并保存本地
/// </summary>
/// <param name="fileName">下载的文件路径(不包括服务器路径 包括后缀)</param>
/// <param name="localPath">保存路径(包括文件名和后缀)</param>
/// <param name="callback">结束回调</param>
/// <returns>下载文件携程</returns>
private IEnumerator DownLoadFile(string filePath, string localPath, UnityAction<bool> callback = null)
{
//下载的文件路劲 serverPath 为服务器所存放AB包的目录 这里使用的是本地服务器 例如:serverPath == "http://127.0.0.1:8800/Game/"
string requestPath =
#if UNITY_EDITOR
serverPath + "PC/" + filePath;
#else
serverPath + "Android/" + filePath;
#endif
UnityWebRequest unityWebRequest = UnityWebRequest.Get(requestPath);
yield return unityWebRequest.SendWebRequest();
//没有出现错误并且下载完毕
if(!unityWebRequest.isHttpError && !unityWebRequest.isNetworkError && unityWebRequest.isDone)
{
//将文件保存到本地
using (FileStream fileStream = File.Create(localPath))
{
fileStream.Write(unityWebRequest.downloadHandler.data, 0, unityWebRequest.downloadHandler.data.Length);
}
//回调成功
Debug.Log("下载" + filePath + "成功");
if (callback != null)
{
callback(true);
}
}
else
{
//回调失败
Debug.Log("下载" + filePath + "失败");
if (callback != null)
{
callback(false);
}
}
}
4.下载AB包对比文件
//服务器AB包对比文件名 以及 本地AB包对比文件名
private static string remoteABCompareName = "ABCompareInfo.txt";
/// <summary>
/// 下载AB包对比文件
/// </summary>
/// <param name="callback">结束回调</param>
private void DownLoadABCompareFile(UnityAction<bool> callback = null)
{
//开启下载 remoteABCompareName 文件携程 remoteABCompareName为AB包对比文件名 例如:remoteABCompareName == "ABCompareInfo.txt"
//下载完成后会保存到 数据持久化路径Application.persistentDataPath
StartCoroutine(DownLoadFile(remoteABCompareName, Application.persistentDataPath + "/" + remoteABCompareName, isDown =>
{
if (isDown)
{
//这里代表已经下载并保存到本地完成
if (callback != null)
{
callback(true);
}
}
else
{
if (callback != null)
{
callback(false);
}
}
}));
}
至此,已经完成AB包对比文件的下载。将 [ http://127.0.0.1:8800/Game/ABCompareInfo.txt ](本地服务器的AB包对比文件)下载下来,并保存为[ Application.persistentDataPath + "/" + ABCompareInfo.txt ]。
5.失败后多次下载的优化
用户由于网络不稳定,会出现下载失败的情况,因此设计自动重新下载的次数,让用户在规定次数中,无需手动进行下载。
//从服务器下载下来后,临时保存的对比文件路径名
private static string localABCompareName = "ABCompareInfo_TMP.txt";
//是否成功下载AB包对比文件
private bool isSuccDownLoadABCompare = false;
//重新下载AB包对比文件次数
private int reDownLoadCompareMaxNums = 5;
//当前下载AB包对比文件次数
private int downLoadCompareNums = 0;
/// <summary>
/// 下载AB包对比文件
/// </summary>
/// <param name="callback">结束回调</param>
private void DownLoadABCompareFile(UnityAction<bool> callback = null)
{
//没有成功下载,并且下载次数小于重新下载最大次数
if (!isSuccDownLoadABCompare && downLoadCompareNums < reDownLoadCompareMaxNums)
{
downLoadCompareNums++;
//开启下载 remoteABCompareName 文件携程 remoteABCompareName为AB包对比文件名 例如:localABCompareName == remoteABCompareName == "ABCompareInfo.txt"
//下载完成后会保存到 数据持久化路径Application.persistentDataPath
StartCoroutine(DownLoadFile(remoteABCompareName, Application.persistentDataPath + "/" + localABCompareName, isDown =>
{
if (isDown)
{
//这里代表已经下载并保存到本地完成
if (callback != null)
{
callback(true);
}
isSuccDownLoadABCompare = true;
}
else
{
Debug.Log("下载" + remoteABCompareName + "失败,重试[" + downLoadCompareNums + "]次");
//下载方法回调失败
isSuccDownLoadABCompare = false;
if (downLoadCompareNums < reDownLoadCompareMaxNums)
{
//还可以重新下载
DownLoadABCompareFile(callback);
}
else
{
//重新下载次数用尽 回调失败
if (callback != null)
{
callback(false);
}
}
}
}));
}
}
6.收集AB包对比文件的信息
private class ABInfo
{
public string name;
public long size;
public string md5;
public ABInfo(string name, string size, string md5)
{
this.name = name;
this.size = long.Parse(size);
this.md5 = md5;
}
}
private Dictionary<string, ABInfo> remoteABInfo = new Dictionary<string, ABInfo>();
/// <summary>
/// AB包对比文件信息收集
/// </summary>
/// <param name="callback">收集结束回调</param>
private void GetABCompareFileInfo(UnityAction<bool> callback)
{
if(!File.Exists(Application.persistentDataPath + "/" + remoteABCompareName))
{
//路劲不存在的情况下
if (callback != null)
{
//回调收集信息失败
callback(false);
return;
}
}
//读取下载的AB包对比文件路径
string info = File.ReadAllText(Application.persistentDataPath + "/" + remoteABCompareName);
//将数据信息拆分成每个AB包信息
string[] strs = info.Split('|');
string[] infos = null;
for (int i = 0; i < strs.Length; i++)
{
//将每个AB包信息拆分成独立数据
infos = strs[i].Split(' ');
//使用 remoteABInfo 字典和 ABInfo 类存储AB包信息
remoteABInfo.Add(infos[0], new ABInfo(infos[0], infos[1], infos[2]));
}
if(callback != null)
{
//回调收集成功
callback(true);
}
}
7.下载AB包
//AB包待下载List集合 用于存储AB包的相对路径名
private List<string> downLoadList = new List<string>();
/// <summary>
/// 对比信息后 下载AB包
/// </summary>
/// <param name="callback">结束回调</param>
/// <returns></returns>
private IEnumerator DownLoadABFile(UnityAction<bool> callback = null)
{
string localPath = Application.persistentDataPath + "/";
//临时List集合:用于记录成功下载的AB文件名
List<string> tempList = new List<string>();
//最大允许重新下载次数
int reDownLoadABFileMaxNums = 5;
//下载次数
int downLoadABFileNums = 0;
//下载成功个数
int downLoadOverNums = 0;
//待下载总数
int downLoadOverMaxNums = downLoadList.Count;
//待下载总数大于0 并且 下载次数在允许重新在次数中
while (downLoadList.Count > 0 && downLoadABFileNums < reDownLoadABFileMaxNums)
{
//下载次数增加
downLoadABFileNums++;
//下载集合中开始下载
for (int i = 0; i < downLoadList.Count; i++)
{
//在本地创建目录供AB包保存
string[] relativePaths = downLoadList[i].Split('/');
string tmpDir = localPath;
for(int j = 0; j < relativePaths.Length - 1; j++)
{
tmpDir = tmpDir + relativePaths[j];
if (!Directory.Exists(tmpDir))
{
Directory.CreateDirectory(tmpDir);
}
tmpDir = tmpDir + "/";
}
//开启下载文件协程 downLoadList[i] 文件名 localPath + downLoadList[i] 保存地址 下载结束回调
yield return StartCoroutine(DownLoadFile(downLoadList[i], localPath + downLoadList[i], isDown =>
{
if(isDown)
{
//下载成功 记录下载的文件
tempList.Add(downLoadList[i]);
downLoadOverNums++;
}
}));
Debug.Log("下载AB包进度:" + downLoadOverNums + "/" + downLoadOverMaxNums);
}
//将下载成功的文件名从待下载列表删除
for (int i = 0; i < tempList.Count; i++)
{
downLoadList.Remove(tempList[i]);
}
//清空记录的文件名List集合
tempList.Clear();
//如果待下载集合中还有文件没下载继续循环
}
if(downLoadList.Count == 0)
{
//待下载集合没有内容,下载所有的AB包成功
if (callback != null)
{
//回调成功
callback(true);
}
}
else
{
//下载失败
if (callback != null)
{
//回调失败
callback(false);
}
}
}
至此,已经可以根据AB包对比文件中的AB包信息下载AB包。将 remoteABInfo 中的key添加到downLoadList中,就能够完成AB包对比文件中所包含的AB包的下载。
添加到 DownLoadABFile 协程中,写在用到 downLoadList 的代码 之前。
foreach (string name in remoteABInfo.Keys)
{
downLoadList.Add(name);
}
8.添加待下载AB包路径名的逻辑及代码优化
待下载List集合需添加AB包路径名进行下载的逻辑:
- 客户端未包含任何AB包,需要下载读取到的对比文件中所有的AB包。
- 客户端包含部分AB包,需要下载本地对比文件中没有保存的AB包。
- 客户端包含部分旧的AB包,需要对比本地对比文件和服务器对比文件,从而下载最新的AB包。
根据项目不同情况,将部分AB包 及 这部分AB包的信息文件(AB包对比文件)存放在 streamingAssetsPath 中,跟随包一起导出。或者不将任何AB包跟随包一起导出。因此,从服务器下载AB包对比文件后,如果包中原本存在AB包对比文件,则需要对比两个文件,从而确定要进行下载或者更新的AB包,从而添加到待下载队列进行下载,之后记得更新本地AB包对比文件。
a.优化AB包对比文件信息,达到重用目的
//服务器对比文件信息
private Dictionary<string, ABInfo> remoteABInfo = new Dictionary<string, ABInfo>();
//本地对比文件信息
private Dictionary<string, ABInfo> localABInfo = new Dictionary<string, ABInfo>();
/// <summary>
/// AB包对比文件信息收集(更新)
/// </summary>
/// <param name="filePath">对比文件路径</param>
/// <param name="dic">存放信息的对应字典</param>
/// <param name="callback">收集结束回调</param>
private void GetABCompareFileInfo(string filePath, Dictionary<string, ABInfo> dic, UnityAction<bool> callback)
{
if (!File.Exists(filePath))
{
//路劲不存在的情况下
if (callback != null)
{
//回调收集信息失败
callback(false);
return;
}
}
//读取下载的AB包对比文件路径
string info = File.ReadAllText(filePath);
//将数据信息拆分成每个AB包信息
string[] strs = info.Split('|');
string[] infos = null;
for (int i = 0; i < strs.Length; i++)
{
//将每个AB包信息拆分成独立数据
infos = strs[i].Split(' ');
//使用字典和 ABInfo 类存储AB包信息
dic.Add(infos[0], new ABInfo(infos[0], infos[1], infos[2]));
}
if (callback != null)
{
//回调收集成功
callback(true);
}
}
b.判断并收集本地AB包对比文件信息
/// <summary>
/// 根据本地最新AB对比文件 收集信息
/// </summary>
/// <param name="callback">收集结束回调</param>
private void GetLocalABCompareFileInfo(UnityAction<bool> callback)
{
if (File.Exists(Application.persistentDataPath + "/" + remoteABCompareName))
{
//Application.persistentDataPath + "/" + remoteABCompareName 指的是之后更新后的本地AB包对比文件
GetABCompareFileInfo(Application.persistentDataPath + "/" + remoteABCompareName, localABInfo, callback);
}
else if(File.Exists(Application.streamingAssetsPath + "/" + remoteABCompareName))
{
//Application.streamingAssetsPath + "/" + remoteABCompareName 指的是初始跟随包一起导出的AB包对比文件
GetABCompareFileInfo(Application.streamingAssetsPath + "/" + remoteABCompareName, localABInfo, callback);
}
else
{
//没有AB包对比文件
//没有AB包对比文件代表没有AB包,所以本地AB包信息应当清空
localABInfo.Clear();
//默认成功收集本地AB包信息
callback(true);
}
}
c.两AB包对比文件进行对比的逻辑
从服务器下载下来的AB包对比文件(localABCompareName)与本地存在的AB包对比文件(remoteABCompareName)进行对比。
/// <summary>
/// 检查是否需要更新资源
/// </summary>
/// <param name="overCallback">结束回调</param>
public void CheckUpdate(UnityAction<bool> overCallback)
{
//清空服务器对比文件信息及本地对比文件信息的字典 及 待下载List集合
remoteABInfo.Clear();
localABInfo.Clear();
downLoadList.Clear();
//从服务器下载AB包对比文件 服务器AB包对比文件名字:remoteABCompareName 保存到本地后的AB包对比文件名字:localABCompareName
DownLoadABCompareFile(isOver =>
{
if (isOver)
{
//下载成功
//收集从服务器下载下来的AB包对比文件信息 并 保存到 remoteABInfo 字典中
GetABCompareFileInfo(Application.persistentDataPath + "/" + localABCompareName, remoteABInfo, overCallback);
//服务器AB包对比文件信息收集成功
//获取本地AB对比文件 并 收集对比文件信息 保存到localABInfo中
GetLocalABCompareFileInfo(isCollect =>
{
if (isCollect)
{
//本地AB包对比文件信息收集成功
//获取本地AB包对比文件的成功回调
foreach (string abName in remoteABInfo.Keys)
{
if (!localABInfo.ContainsKey(abName))
{
//将本地没有的AB包路径名添加到待下载List集合中
downLoadList.Add(abName);
}
else
{
//本地有的AB包则需要对比两者MD5码是否一样
if (localABInfo[abName].md5 != remoteABInfo[abName].md5)
{
//MD5码不一样,代表本地AB包不是最新的,需要下载,因此也添加到待下载List集合中
downLoadList.Add(abName);
}
//检查后删除与服务器一样的资源信息
localABInfo.Remove(abName);
}
}
foreach (string abName in localABInfo.Keys)
{
//本地多出来的无用AB包需要进行删除
if (File.Exists(Application.persistentDataPath + "/" + abName))
{
File.Delete(Application.persistentDataPath + "/" + abName);
}
}
//两AB包对比文件对比结束 开始下载AB包
StartCoroutine(DownLoadABFile(isFinish =>
{
if (isFinish)
{
//完成后 更新本地AB包对比文件
string remoteInfo = File.ReadAllText(Application.persistentDataPath + "/" + localABCompareName);
File.WriteAllText(Application.persistentDataPath + "/" + remoteABCompareName, remoteInfo);
}
else
{
Debug.Log("下载AB包失败");
}
//下载AB包结束 回调结束
overCallback(isFinish);
}));
}
else
{
//收集本地AB包对比信息失败 回调失败
overCallback(false);
}
});
}
else
{
//下载服务器AB包对比文件失败 回调失败
overCallback(false);
}
});
}
至此,整个流程基本结束。下载AB包对比文件,并与存在本地的AB包对比文件进行对比,之后下载最新和缺失的AB包。
9.优化资源更新判断逻辑,加入自定义消息回调
/// <summary>
/// 下载回调类型
/// </summary>
public enum DownCallbackType
{
None,
Message,
Progress
}
/// <summary>
/// 检查是否需要更新资源
/// </summary>
/// <param name="overCallback">结束回调</param>
public void CheckUpdate(UnityAction<bool> overCallback, UnityAction<DownCallbackType, string> updateCallback)
{
//清空服务器对比文件信息及本地对比文件信息的字典 及 待下载List集合
remoteABInfo.Clear();
localABInfo.Clear();
downLoadList.Clear();
updateCallback(DownCallbackType.Message, "下载的本地路径|" + Application.persistentDataPath);
//从服务器下载AB包对比文件 服务器AB包对比文件名字:remoteABCompareName 保存到本地后的AB包对比文件名字:localABCompareName
DownLoadABCompareFile(isOver =>
{
if(isOver)
{
//下载成功
updateCallback(DownCallbackType.Message, "下载服务器对比文件成功");
//收集从服务器下载下来的AB包对比文件信息 并 保存到 remoteABInfo 字典中
GetABCompareFileInfo(Application.persistentDataPath + "/" + localABCompareName, remoteABInfo, overCallback);
updateCallback(DownCallbackType.Message, "服务器AB包对比文件信息收集成功");
//服务器AB包对比文件信息收集成功
//获取本地AB对比文件 并 收集对比文件信息 保存到localABInfo中
GetLocalABCompareFileInfo(isCollect =>
{
if (isCollect)
{
//本地AB包对比文件信息收集成功
//获取本地AB包对比文件的成功回调
updateCallback(DownCallbackType.Message, "本地AB包对比文件信息收集成功");
foreach (string abName in remoteABInfo.Keys)
{
if(!localABInfo.ContainsKey(abName))
{
//将本地没有的AB包路径名添加到待下载List集合中
downLoadList.Add(abName);
}
else
{
//本地有的AB包则需要对比两者MD5码是否一样
if (localABInfo[abName].md5 != remoteABInfo[abName].md5)
{
//MD5码不一样,代表本地AB包不是最新的,需要下载,因此也添加到待下载List集合中
downLoadList.Add(abName);
}
//检查后删除与服务器一样的资源信息
localABInfo.Remove(abName);
}
}
foreach(string abName in localABInfo.Keys)
{
//本地多出来的无用AB包需要进行删除
if (File.Exists(Application.persistentDataPath + "/" + abName))
{
File.Delete(Application.persistentDataPath + "/" + abName);
}
}
updateCallback(DownCallbackType.Message, "两AB包对比文件对比结束 开始下载AB包");
//两AB包对比文件对比结束 开始下载AB包
StartCoroutine(DownLoadABFile(isFinish =>
{
if(isFinish)
{
//完成后 更新本地AB包对比文件
string remoteInfo = File.ReadAllText(Application.persistentDataPath + "/" + localABCompareName);
File.WriteAllText(Application.persistentDataPath + "/" + remoteABCompareName, remoteInfo);
updateCallback(DownCallbackType.None, "AB包下载结束");
}
else
{
updateCallback(DownCallbackType.None, "AB包下载失败");
}
//下载AB包结束 回调结束
overCallback(isFinish);
}, updateCallback));
}
else
{
updateCallback(DownCallbackType.Message, "收集本地AB包对比信息失败");
//收集本地AB包对比信息失败 回调失败
overCallback(false);
}
});
}
else
{
updateCallback(DownCallbackType.Message, "下载服务器AB包对比文件失败");
//下载服务器AB包对比文件失败 回调失败
overCallback(false);
}
});
}
/// <summary>
/// 对比信息后 下载AB包
/// </summary>
/// <param name="callback">结束回调</param>
/// <param name="updateCallback">消息回调</param>
/// <returns></returns>
private IEnumerator DownLoadABFile(UnityAction<bool> callback = null, UnityAction<DownCallbackType, string> updateCallback = null)
{
//foreach (string name in remoteABInfo.Keys)
//{
// downLoadList.Add(name);
//}
string localPath = Application.persistentDataPath + "/";
//临时List集合:用于记录成功下载的AB文件名
List<string> tempList = new List<string>();
//最大允许重新下载次数
int reDownLoadABFileMaxNums = 5;
//下载次数
int downLoadABFileNums = 0;
//下载成功个数
int downLoadOverNums = 0;
//待下载总数
int downLoadOverMaxNums = downLoadList.Count;
//待下载总数大于0 并且 下载次数在允许重新在次数中
while (downLoadList.Count > 0 && downLoadABFileNums < reDownLoadABFileMaxNums)
{
//下载次数增加
downLoadABFileNums++;
//下载集合中开始下载
for (int i = 0; i < downLoadList.Count; i++)
{
//在本地创建目录供AB包保存
string[] relativePaths = downLoadList[i].Split('/');
string tmpDir = localPath;
for(int j = 0; j < relativePaths.Length - 1; j++)
{
tmpDir = tmpDir + relativePaths[j];
if (!Directory.Exists(tmpDir))
{
Directory.CreateDirectory(tmpDir);
}
tmpDir = tmpDir + "/";
}
//开启下载文件协程 downLoadList[i] 文件名 localPath + downLoadList[i] 保存地址 下载结束回调
yield return StartCoroutine(DownLoadFile(downLoadList[i], localPath + downLoadList[i], isDown =>
{
if(isDown)
{
//下载成功 记录下载的文件
tempList.Add(downLoadList[i]);
downLoadOverNums++;
}
}));
//Debug.Log("下载AB包进度:" + downLoadOverNums + "/" + downLoadOverMaxNums);
updateCallback(DownCallbackType.Progress, downLoadOverNums + "/" + downLoadOverMaxNums);
}
//将下载成功的文件名从待下载列表删除
for (int i = 0; i < tempList.Count; i++)
{
downLoadList.Remove(tempList[i]);
}
//清空记录的文件名List集合
tempList.Clear();
//如果待下载集合中还有文件没下载继续循环
}
if(downLoadList.Count == 0)
{
//待下载集合没有内容,下载所有的AB包成功
if (callback != null)
{
//回调成功
callback(true);
}
}
else
{
//下载失败
if (callback != null)
{
//回调失败
callback(false);
}
}
}
10.在外部代码中调用的方法
CheckUpdate(isOver =>
{
if (isOver)
{
Debug.Log("下载结束, 跳转场景");
}
else
{
Debug.Log("失败,弹出重新游戏弹框");
}
}, (callbackType, message) =>
{
switch (callbackType)
{
case DownCallbackType.Message:
Debug.Log(message);
break;
case DownCallbackType.Progress:
Debug.Log("AB包下载进度:" + message);
break;
}
});
因为作者精力有限,文章中难免出现一些错漏,敬请广大专家和网友批评、指正。