Unity的资源更新

目录:

1、有资源更新需求时,资源的存储方式

2、下载资源的两种方式

3、断点续传的方式

 

在项目中。资源的更新是网络游戏中必不可少的一个环节。本文谈的是如何管理和下载资源

 

1、有资源更新需求时,资源的存储方式和读取方式

Unity提供了两个目录来存放资源:

streamingAssetsPath:此路径下的文件只能读取。不能写入。文件随包的生成打入包中。不能修改

persistentDataPath:一个持久化路径,可以读取和写入

在有自动更新的需求时,需要决定哪些文件放入streamingAssetsPath里,另外一下用于自动更新,存在persistentDataPath里面。1)全部放到streamingAssetsPath文件夹里,打出的包就会大,而且更新频繁的话,资源就会存在两份,persistentDataPath也会有一份资源,这样就会形成一个特别大的包。(刚开始做游戏的时候。做过一个特别傻的事,就是为了加载的时候方便一些。开始的时候把streamingAssetsPath里面的文件拷贝到persistentDataPath里。这样一开始就出现特别大的包)

2)只放自动更新的UI资源。其他的资源要从网上下载。这样第一次开游戏的时候。会更新很久。

3)还有一种方式就是放入初始一部分资源。到游戏进行的某个阶段的时候,再进行阶段性的更新。这样做的方式就是操作复杂。

根据项目的需求。一般都会选中1和3这两种方式。2在第一次开始游戏的时候。等待长时间的下载。体验实在太差,开始游戏的前几分钟。是留存的关键。所以不建议用2的方式。先说说方式1如何获取需要更新的文件,方式3只是1的变种

在更新的时,需要判断哪些文件需要自动更新。不可能把每个文件都下载下来之后。再比对MD5码,然后才能确定是不是更新文件。要不要保存。这个时候,在服务器端需要有一个Index文件。里面保存了文件名称、MD5码、文件长度。在客户端也需要一个相应的文件在persistentDataPath中(需要修改,只能在这个文件夹里),就叫local.version。该文件保存了文件名、MD5码、文件是否在streamingAssetsPath的标记(1:文件在streamingAssetsPath,0:文件在persistentDataPath),这个标记用于资源加载的时候。觉得从哪个文件夹去加载文件

在第一次启动游戏时,需要把streamingAssetsPath文件夹里面的文件的数据。写入到local.version中。在local.version中就有记录客户端最新的资源是哪个版本。再和服务器上面的Index文件对比之后。就能找出需要更新的文件

方式3就是在服务器端有多个Index文件。比如Index1、Index2等等,后面的Index数据包含前面的Index文件数据。这样每次只要对比相应的Index文件就能找到需要更新的文件,通过游戏进程来判断找哪个Index文件做比较

要读取streamingAssetsPath里面的文件,正常的IO操作是不读取不了的。得要用www的方式来读取文件,不同的平台,需要添加不同的后缀

string getStreamingPath_for_www()
{
        string pre = "file://";
#if UNITY_EDITOR
        pre = "file://";
#elif UNITY_ANDROID
        pre = "";
#elif UNITY_IPHONE
	    pre = "file://";
#endif
        string path = pre + Application.streamingAssetsPath + "/";
        return path;
}

以拷贝数据为例,拷贝streamingAssetsPath文件夹下面名为fileName的文件拷贝到persistentDataPath中

    IEnumerator copy(string fileName)
    {
        string src = getStreamingPath_for_www() + fileName;
        string des = Application.persistentDataPath + "/" + fileName;
        WWW www = new WWW(src);
        yield return www;
        if (!string.IsNullOrEmpty(www.error))
        {
            Debug.Log("www.error:" + www.error);
        }
        else
        {
            if (File.Exists(des))
            {
                File.Delete(des);
            }
            FileStream fsDes = File.Create(des);
            fsDes.Write(www.bytes, 0, www.bytes.Length);
            fsDes.Flush();
            fsDes.Close();
        }
        www.Dispose();
    }

确定了哪些需要更新的文件。接下来要做的就是更新操作

2、下载的接口有两种,一种是Unity自动的API:UnityWebRequest,另外一个是C#的HttpWebRequest功能

1)UnityWebRequest:Unity用于处理Web服务器Http通信流,包含上传和下载的功能,这里只用其中的下载功能。如示例所示,简单的下载只要提供一个Url就行

m_aUnityWebRequest = UnityWebRequest.Get(_url);    //下载地址
m_aUnityWebRequest.SendWebRequest();                //请求下载
yield return m_aUnityWebRequest
byte[] arrData = m_aUnityWebRequest.downloadHandler.data    //下载成功的二进制数据

2)HttpWebRequest:C#用于Http通信的类。这个接口是同步读取。会阻塞主线程,所以要新开线程来做资源下载

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_strUrl);    //创建一个HttpWebRequest类,并且传入URL
Stream stream = request.GetResponse().GetResponseStream();     //向服务器请求数据,同步的
int length = stream.Read(buffer, 0, buffer.Length);            //以下是读取数据
while(length > 0)
{
   if (IsStop)
        break;
   fileSteam.Write(buffer, 0, length);
   m_currentLength += length;
   Debug.Log("GetProcess =  " + GetProcess());
   length = stream.Read(buffer, 0, buffer.Length);
}
stream.Close();
stream.Dispose();
request.GetResponse().Close();

3、断点续传:有些文件特别大,一次性下载下来会特别慢,需要分批下载,或者下载中途退出,下次再开始游戏的时候下载过的资源不再重新下载。这样就需要断点续传功能。

断点续传的核心操作是要保存一个临时文件和临时文件的MD5码文件,在重新下载的时候,先检查有没有临时文件以及临时文件的MD5码是否和网上的一直。如果不一致。则证明文件有更新,删除旧的临时文件重新下载。如果一致,则从临时文件的长度从网上获取数据。请求一个区间的数据。需要涉及到Http的报头,Http报头是个哈希表,想知道更多内容自己去查,这里用到的是一个“Range”的Key,Value是一个区间,例如("Range","bytes=50-100")表示请求的数据区间是从50-100

1)UnityWebRequest方式

m_aUnityWebRequest = UnityWebRequest.Get(_url);    //下载地址

m_aUnityWebRequest.SetRequestHeader("Range", "bytes=" + nStartPos.ToString()+ "-" + (nStartPos + CHUNK_SIZE).ToString());        //这个是新增的,请求一个区间的数据

m_aUnityWebRequest.SendWebRequest();                //请求下载
yield return m_aUnityWebRequest
byte[] arrData = m_aUnityWebRequest.downloadHandler.data    //下载成功的二进制数据

2)HttpWebRequest:

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_strUrl);    //创建一个HttpWebRequest类,并且传入URL

request.AddRange((int)m_currentLength);        //这个就是请求的报头接口

Stream stream = request.GetResponse().GetResponseStream();     //向服务器请求数据,同步的
int length = stream.Read(buffer, 0, buffer.Length);            //以下是读取数据
while(length > 0)
{
   if (IsStop)
        break;
   fileSteam.Write(buffer, 0, length);
   m_currentLength += length;
   Debug.Log("GetProcess =  " + GetProcess());
   length = stream.Read(buffer, 0, buffer.Length);
}
stream.Close();
stream.Dispose();
request.GetResponse().Close();

和上面正常下载不同的是,断点续传只是多了一个请求区间的API调用。其他的都是一样

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值