状态
完结撒花🎉
下载
单线程下载与多线程下载
如果是单线程的话,下载资源就需要排队,耗时较长
而多线程下载,则可以开多线程,对一个或多个模块进行下载
下载的流程
首先,下载的时候是按照一个个模块去进行下载的,因而此处的讨论对象是模块,弄懂了下载一个模块的流程,其实对于多模块的下载也就明白了。
下载的流程是这样的:
- 热更版本的比较
- 热更包大小的计算
- 构建下载队列
- 创建下载器和下载线程进行下载
___
热更版本的比较
在HotAssets的根目录下,每个模块都会有一个模块的热更新配置文件,命名为模块名+AssetsHotManifest(比如上图中的HallAssetsHotManifest)
热更版本的比较,就是生成两个比较用的热更新配置文件
Server这个,直接从服务器上下载,并在前面添加前缀命名为Server+模块名+AssetsHotManifest(注意,每次打开游戏拉取时,必然是把最新的覆盖掉本地的)
然后重点来了,Local这个,则是进行比较的核心文件。
如果没有Local这个文件,说明完全没有热更过,那么就是把模块中的所有AB包下载下来,然后生成Local这个文件。
如果有Local这个文件,那么就把这两个文件进行比对,如果不一致的话,说明本地的版本落后了,那么就会根据服务器的热更新配置来添加需要热更的文件,并且把Local文件进行覆盖。
___
热更包大小的计算
首先我们看下热更文件信息HotFileInfo存放的长度是什么单位
从这里,我们可以看到是获取FileInfo的长度,而这个长度的单位是byte
因此,通过除以1024.0f,HotFileInfo的size这个变量存的单位是KB
知道这一点后,我们再对HotFileInfo的size这个变量除以1024.0f,那单位就变成了MB
因而AssetsMaxSizeM这个变量存的就是热更的大小(单位为MB)
构建下载队列
第一步,在获得了要热更的文件列表后,由于我们后面在加载AB包的时候,需要先获得该模块的AB包配置信息,因而我们需要把存放配置的AB包放在第一下载
如图,我们通过insert到0下标的办法,保证List遍历时,第一个是配置文件
第二步,我们把上述已经添加好的List转成一个队列,而后将会把这个队列放到下载器中进行下载
下载器
下载器的简单整体思路是这样的:
1. 下载器需要的主要参数:1.模块信息 2.下载队列 3.下载URL 4.下载文件保存路径 5.成功,失败,结束三个回调
2. 下载器在收到开始下载的命令之后,根据最大线程数,将下载队列中的文件出队,放到新开的线程对象中处理
3. 线程对象会拼接下载URL + 下载文件的信息,从而向地址发出HttpWebRequest请求,方法为"Get"
4. 在得到HttpWebResponse的响应时,获取其响应流,同时通过下载文件保存路径创建本地文件流,而后将HttpWebResponse中的数据写到本地的文件中
新建一个512长的字节数组buffer,我们先从网络流中读取512个字节到buffer中,并且通过返回值得到读取的长度,而后写入到本地文件流filestream中,然后就是不断循环读取,写入,并把相应的数据添加到相应的变量中。
5. 当数据写完之后,就会触发下载成功的回调
通知下载器进行线程的管理,下载器收到通知之后,会将线程移除掉,并把其记录的信息放到队列中(放到队列中记得加锁,因为多线程会有同时操作队列问题),等待Unity主线程去处理(这里要用主线程处理,一个是保证顺序,第二是只有主线程才能访问Unity 对象和 API,所以一般先把线程处理好的结果放到Unity主线程中去处理)
同时会再次检查是否还有需要下载的文件,如果有的话,就会继续开新的线程对象去处理 (可以理解为回到上面的第二步)
6. 如果所有线程的数量为0,说明所有文件都下载完了,此时就会触发所有文件下载完成的回调,将服务器的配置文件替换到本地,至此下载完成
总结
总的流程梳理如下:
- 热更版本的比较
- 热更包大小的计算
- 构建下载队列
- 创建下载器和下载线程进行下载
- 传入下载器需要的参数
- 下载器在收到开始下载的命令之后,将下载队列中的文件出队,放到新开的线程对象中
- 根据资源地址,向地址发出请求,方法为 “Get”
- 获取其响应流后,同时创建本地文件流,而后将响应流中的数据写到本地的文件中
- 当数据写完之后,就会触发下载成功的回调,移除下载协程,并将记录的信息放到主线程的队列中,并且如果还有文件下载的话,回到第二步,继续新开线程下载文件
- 全部文件下载完成后,将服务器配置替换成本地,并触发回调