[Unity]AssetBundle资源更新以及多线程下载

HttpWebRequest request = HttpWebRequest.Create(url) as
HttpWebRequest;

 

                request.ReadWriteTimeout = ReadWriteTimeOut;

                request.Timeout = TimeOutWait;

 

                //断点续传核心,设置远程访问文件流的起始位置

                request.AddRange((int)fileLength);
————————————————
版权声明:本文为CSDN博主「亿洋」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37283423/article/details/77890735

 

[Unity]AssetBundle资源更新以及多线程下载

https://blog.csdn.net/m0_37283423/article/details/77890735

 

此文章适合不太了解资源加载的萌新,有了入门基础之后再去github上搜大牛写的专业的资源加载方案才能得心应手,不然的话会看的很吃力或者说一脸懵逼。Unity里面关于资源加载我们都知道是下载更新AssetBundle,关于AssetBundle我之前的文章已经详细介绍过,没看过的朋友可以在看一下。下面介绍的资源加载的Demo有以下几点:
1.WWW下载图片资源
2.HTTP下载apk文件,并且支持断点续传,并且显示加载进度条
3.HTTP多线程下载文件
部分核心代码和讲解WWW下载思路:
WWW是Unity给我们封装的一个基于HTTP的简单类库,如果我们做很简单的下载,或者网络请求可以用这个类库,个人觉得这个封装的并不是很好,所以一般商业项目开发都不会使用这个,宁可自己去封装一个HTTP请求和下载的类库,可控性更好。仅仅是个人观点,不喜勿喷。
代码:
[C#] 纯文本查看 复制代码
?

 

01

02

03

04

05

06

07

08

09

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
    

using
UnityEngine;

using
System.Collections;

using
System;

using
System.IO;

 

public
class WWWLoad

{

    private
WWW www = null;

    static
System.Diagnostics.Stopwatch stopWatch = new
System.Diagnostics.Stopwatch();

    /// <summary>

    /// 下载文件

    /// </summary>

    public
IEnumerator DownFile(string
url, string
savePath, Action<WWW> process)

    {

        FileInfo file = new
FileInfo(savePath);

        stopWatch.Start();

        UnityEngine.Debug.Log("Start:"
+ Time.realtimeSinceStartup);

        www = new
WWW(url);

        while
(!www.isDone)

        {

            yield
return 0;

            if
(process != null)

                process(www);

        }

        yield
return www;

        if
(www.isDone)

        {

            byte[] bytes = www.bytes;

            CreatFile(savePath, bytes);

        }

    }

 

    /// <summary>

    /// 创建文件

    /// </summary>

    /// <param name="bytes"></param>

    public
void CreatFile(string
savePath, byte[] bytes)

    {

        FileStream fs = new
FileStream(savePath, FileMode.Append);

        BinaryWriter bw = new
BinaryWriter(fs);

        fs.Write(bytes, 0, bytes.Length);

        fs.Flush();     //流会缓冲,此行代码指示流不要缓冲数据,立即写入到文件。

        fs.Close();     //关闭流并释放所有资源,同时将缓冲区的没有写入的数据,写入然后再关闭。

        fs.Dispose();   //释放流

        www.Dispose();

 

        stopWatch.Stop();

        Debug.Log("下载完成,耗时:"
+ stopWatch.ElapsedMilliseconds);

        UnityEngine.Debug.Log("End:"
+ Time.realtimeSinceStartup);

    }

 

}


HTTP下载并加载AB资源思路:
主要用的核心类是HttpWebRequest,用这个类创建的对象可以申请下载的文件的大小以及下载的进度。移动上可读写的目录是PersidentDataPath,并且各个移动设备的路径不同,这点要注意,所以我们下载的AB资源就会下载到这个目录。
效果图:
核心代码:
3yangyang9,如果您要查看本帖隐藏内容请回复

多线程下载文件思路:
多线程下载思路是计算一个文件包大小,然后创建几个线程,计算每一个线程下载的始末下载的位置,最后是合并成一个整体的文件包写入到本地。
效果图:
核心代码:
[C#] 纯文本查看 复制代码
?

 

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

036

037

038

039

040

041

042

043

044

045

046

047

048

049

050

051

052

053

054

055

056

057

058

059

060

061

062

063

064

065

066

067

068

069

070

071

072

073

074

075

076

077

078

079

080

081

082

083

084

085

086

087

088

089

090

091

092

093

094

095

096

097

098

099

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136
    

using
UnityEngine;

using
System.Collections;

using
System.Threading;

using
System.IO;

using
System.Net;

using
System;

 

/// <summary>

/// 通过http下载资源

/// </summary>

public
class HttpDownLoad {

    //下载进度

    public
float progress{get; private
set;}

    //涉及子线程要注意,Unity关闭的时候子线程不会关闭,所以要有一个标识

    private
bool isStop;

    //子线程负责下载,否则会阻塞主线程,Unity界面会卡主

    private
Thread thread;

    //表示下载是否完成

    public
bool isDone{get; private
set;}

    const
int ReadWriteTimeOut = 2 * 1000;//超时等待时间

    const
int TimeOutWait = 5 * 1000;//超时等待时间

 

 

    /// <summary>

    /// 下载方法(断点续传)

    /// </summary>

    /// <param name="url">URL下载地址</param>

    /// <param name="savePath">Save path保存路径</param>

    /// <param name="callBack">Call back回调函数</param>

    public
void DownLoad(string
url, string
savePath,string
fileName, Action callBack, System.Threading.ThreadPriority threadPriority = System.Threading.ThreadPriority.Normal)

    {

        isStop = false;

        System.Diagnostics.Stopwatch stopWatch = new
System.Diagnostics.Stopwatch();

        //开启子线程下载,使用匿名方法

        thread = new
Thread(delegate() {

            stopWatch.Start();

            //判断保存路径是否存在

            if
(!Directory.Exists(savePath))

            {

                Directory.CreateDirectory(savePath);

            }

            //这是要下载的文件名,比如从服务器下载a.zip到D盘,保存的文件名是test

            string
filePath = savePath + "/"+ fileName;

 

            //使用流操作文件

            FileStream fs = new
FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);

            //获取文件现在的长度

            long
fileLength = fs.Length;

            //获取下载文件的总长度

            UnityEngine.Debug.Log(url+" "+fileName);

            long
totalLength = GetLength(url);

            Debug.LogFormat("<color=red>文件:{0} 已下载{1}M,剩余{2}M</color>",fileName,fileLength/1024/1024,(totalLength- fileLength)/ 1024/1024);        

 

            //如果没下载完

            if(fileLength < totalLength)

            {

 

                //断点续传核心,设置本地文件流的起始位置

                fs.Seek(fileLength, SeekOrigin.Begin);

 

                HttpWebRequest request = HttpWebRequest.Create(url) as
HttpWebRequest;

 

                request.ReadWriteTimeout = ReadWriteTimeOut;

                request.Timeout = TimeOutWait;

 

                //断点续传核心,设置远程访问文件流的起始位置

                request.AddRange((int)fileLength);

 

                Stream  stream = request.GetResponse().GetResponseStream();

                byte[] buffer = new
byte[1024];

                //使用流读取内容到buffer中

                //注意方法返回值代表读取的实际长度,并不是buffer有多大,stream就会读进去多少

                int
length = stream.Read(buffer, 0, buffer.Length);

                //Debug.LogFormat("<color=red>length:{0}</color>" + length);

                while
(length > 0)

                {

                    //如果Unity客户端关闭,停止下载

                    if(isStop) break;

                    //将内容再写入本地文件中

                    fs.Write(buffer, 0, length);

                    //计算进度

                    fileLength += length;

                    progress = (float)fileLength / (float)totalLength;

                    //UnityEngine.Debug.Log(progress);

                    //类似尾递归

                    length = stream.Read(buffer, 0, buffer.Length);

 

                }

                stream.Close();

                stream.Dispose();

 

            }

            else

            {

                progress = 1;

            }

            stopWatch.Stop();

            Debug.Log("耗时: " + stopWatch.ElapsedMilliseconds);

            fs.Close();

            fs.Dispose();

            //如果下载完毕,执行回调

            if(progress == 1)

            {

                isDone = true;

                if
(callBack != null) callBack();

                thread.Abort();

            }

            UnityEngine.Debug.Log ("download finished");   

        });

        //开启子线程

        thread.IsBackground = true;

        thread.Priority = threadPriority;

        thread.Start();

    }

 

 

    /// <summary>

    /// 获取下载文件的大小

    /// </summary>

    /// <returns>The length.</returns>

    /// <param name="url">URL.</param>

    long
GetLength(string
url)

    {

        UnityEngine.Debug.Log(url);

 

        HttpWebRequest requet = HttpWebRequest.Create(url) as
HttpWebRequest;

        requet.Method = "HEAD";

        HttpWebResponse response = requet.GetResponse() as
HttpWebResponse;

        return
response.ContentLength;

    }

 

    public
void Close()

    {

        isStop = true;

    }

 

}


线程下载速度跟线程的关系呈钟罩式关系,也就是说适量的线程数量会提高下载速度,但并不是说线程数越多就越好,因为线程的切换和资源的整合也是需要时间的。下面就列举下载单个文件,创建的线程数和对应的下载时间:

    单线程
    5个线程
    15个线程

这里我是1M的带宽,下载的是一个300KB左右的资源,一般不会做多线程下载单一资源,多线程下载一般用于下载多个资源,除非单一资源真的很大才有多线程下载,然后做合包操作。
————————————————
版权声明:本文为CSDN博主「亿洋」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37283423/article/details/77890735

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值