Unity3d 基于xlua热更新实现系列四(终章):构建资源服务器实现真正热更新的压缩包下载、解压和更新功能(含源码)

前言

上三篇,我们实现了:
Unity3d 基于xlua热更新实现系列一:登录功能熟悉lua重写C#
Unity3d 基于xlua热更新实现系列二:Xlua脚本动态加载(半热更新)
Unity3d 基于xlua热更新实现系列三:生成AB包导出并实现AB包动态加载(资源半热更改)
探索了,资源更新和逻辑脚本等功能。完整热更新在本文推出,时间花的有点久,主要还是因为更新界面打算用xlua编写的,可是编写了一半放弃了,实在是不顺手啊(任重道远~~~),最后纯C#编写了更新检测、资源下载、解压更新等功能。

效果

在这里插入图片描述

资源服务器

资源服务器的搭建我是比较从简的方式直接使用了IIS,按如下的方式进行配置:
在这里插入图片描述

在E盘新增了HotUpdateServer目录,设置为服务器的根目录。
在下面新建了ResVers文件夹,用于存放更新的内容。versions.json文件是版本的描述文件,用于检查更新时访问。

{
    
    
	"versions": [
		{
    
    
			"ver": "1.0",
			"url": "http://127.0.0.1:5544/ResVers/Ver1.0.zip",
			"content": "基础版本的更新内容"
		},
		{
    
    
			"ver": "1.1",
			"url": "http://127.0.0.1:5544/ResVers/Ver1.1.zip",
			"content": "更新了登录界面的面板文字,更新了登录场景的的模型运动,"
		}
	]
}

更新功能

更新功能是程序运行的第一个功能,先检查更新,根据本地资源的版本号请求服务器资源,有更新时开始下载资源,下载完成一个资源更新本地的资源同时更新本地版本号,直到资源是服务器最新版本的资源。

搭建UI

按如图的形式搭建更新界面的UI:
在这里插入图片描述

主要的内容是:上面的更新内容的描述 和下方的更新进度UI。

检查更新

本地使用了一个version.json文件记录本地的版本信息:

{
    
    "version":"1.1"}

检查更新时我们先读取本地资源版本,再请求服务器资源版本。

 //检查版本
    IEnumerator CheckVersions()
    {
    
    
        WebReq = UnityWebRequest.Get(VerChkUrl);
        isProc = true;
        WebReq.SendWebRequest();
        if (WebReq.isNetworkError || WebReq.isHttpError)                                                            
        {
    
    
            Debug.Log(WebReq.error); 
        }
        else
        {
    
    
            while (!WebReq.isDone) 
            {
    
    
                if (WebReq.downloadProgress != 0)
                    yield return 0;
            }
            if (WebReq.isDone) 
            {
    
    
                JsonData data = JsonMapper.ToObject(WebReq.downloadHandler.text);
                if (data.ContainsKey("versions") && data["versions"] != null && data["versions"].IsArray)
                {
    
    
                    VersionList.Clear();
                    for (int i = 0; i < data["versions"].Count; i++)
                    {
    
    
                        Version temp = JsonMapper.ToObject<Version>(data["versions"][i].ToJson());
                        VersionList.Add(temp);
                    }
                }
                isProc = false;
                GetUpdateList();
            }
        }
}

根据请求回来的服务器资源版本和本地进行对比,获取需要更新列表:

    void GetUpdateList() {
    
    
        UpdateVerList.Clear();
        bool isNext = false;
        for (int i = 0; i < VersionList.Count; i++) {
    
    
            if (!isNext) {
    
    
                UpdateVerList.Add(VersionList[i]);
                if (VersionList[i].ver == version) {
    
    
                    UpdateVerList.Clear ();
                    isNext = true;
                }
            }else
                UpdateVerList.Add(VersionList[i]);
        }
        UpdateVerUIList();
        TipText.text = "检查更新完成!";
        RateText.text = "100.00%";
        RateImg.fillAmount = 1;
        if (UpdateVerList.Count > 0) {
    
    
            idx = 0;
            StartCoroutine(DownloadRes(UpdateVerList[0]));
        }
    }

资源下载

检查完需要更新时,将服务器的资源下载到本地,下载的同时更新下载进度:

扫描二维码关注公众号,回复: 14189836 查看本文章
    IEnumerator DownloadRes(Version verinfo)
    {
    
    
        VerCountText.text = "更新进度:"+(idx+1)+"/"+ UpdateVerList.Count; 
        TipText.text = "资源下载中,请勿退出更新";
        isProc = true;
        WebReq = UnityWebRequest.Get(verinfo.url); 
        WebReq.SendWebRequest();
        if (WebReq.isNetworkError || WebReq.isHttpError)                                                         
        {
    
    
            Debug.Log(WebReq.error); 
        }
        else
        {
    
    
            while (!WebReq.isDone) 
            {
    
    
                if (WebReq.downloadProgress != 0)
                    yield return 0;
            }

            if (WebReq.isDone)
            {
    
    
                WriteByte(TempPath + GetNameByPath(verinfo.url), WebReq.downloadHandler.data);
                isProc = false;
                StartCoroutine(UnZipFile(verinfo));
            }
        }
        yield return null;
}

解压更新资源

解压资源我们采用了ICSharpCode.SharpZipLib插件,可以自行搜索github上下载。

我们下载完成一个资源就会解压更新,更新完成后会清除资源,继续下载下一个资源:

    IEnumerator  UnZipFile(Version verinfo)
    {
    
    
        TipText.text = "解压资源中,请勿退出!";
        string spath = TempPath + GetNameByPath(verinfo.url);
        if (!File.Exists(spath))
        {
    
    
            Debug.LogError("没有此文件路径:" + spath);
            yield return null;
        }
        using (ZipInputStream stream = new ZipInputStream(File.OpenRead(spath)))
        {
    
    
            ZipEntry theEntry;
            while ((theEntry = stream.GetNextEntry()) != null)
            {
    
    
                string fileName = Path.GetFileName(theEntry.Name);
                string filePath = Path.Combine(Application.dataPath+ "/HotUpdateRes/", theEntry.Name);
                string directoryName = Path.GetDirectoryName(filePath);

                if (directoryName.Length > 0)
                    if (!Directory.Exists(directoryName))
                        Directory.CreateDirectory(directoryName);
                if (fileName != String.Empty)
                {
    
    
                    using (FileStream streamWriter = File.Create(filePath))
                    {
    
    
                        int size = 2048;
                        byte[] data = new byte[2048];
                        while (true)
                        {
    
    
                            size = stream.Read(data, 0, data.Length);
                            if (size > 0)
                                streamWriter.Write(data, 0, size);
                            else
                                break;
                        }
                        streamWriter.Close();
                        streamWriter.Dispose();
                    }
                }
                yield return 0;
            }
            stream.Close();
            stream.Dispose();
            File.Delete(spath);
            SetVersion(verinfo.ver);
        }
        TipText.text = "解压资源完成!";
        if (idx < UpdateVerList.Count - 1)
        {
    
    
            idx++;
            StartCoroutine(DownloadRes(UpdateVerList[idx]));
        }
        else
        {
    
    
            if (Main.instance != null)
                Main.instance.ShowLogin();
        }
    }

验证热更新

我们将上篇文章中的更新作为1.1版本,本地版本为1.1,然后更改些内容为1.2版本。

处理资源版本

这一步的ab包我们在之前一篇文章中介绍了,这里只是制作1.2更新版本。
将登录场景的模型增多:

在这里插入图片描述

修改登录逻辑脚本,使Cube上下移动:

local MoveUp = false
function update()
	local r = CS.UnityEngine.Vector3.up * CS.UnityEngine.Time.deltaTime * speed
	cubeObj.transform:Rotate(r)
	if(MoveUp) then
	     cubeObj.transform.localPosition =  cubeObj.transform.localPosition + CS.UnityEngine.Vector3.up*0.02;
	else
	     cubeObj.transform.localPosition = cubeObj.transform.localPosition - CS.UnityEngine.Vector3.up*0.02;
    end
	if(cubeObj.transform.localPosition.y >5)then
	    MoveUp = false
	elseif(cubeObj.transform.localPosition.y <-3) then
	    MoveUp = true
	end
	lightCpnt.color = CS.UnityEngine.Color(CS.UnityEngine.Mathf.Sin(CS.UnityEngine.Time.time) / 2 + 0.5, 0, 0, 1)
end

完成后将资源打包为Ver1.2.zip。

版本修改

这里我修改服务器版本配置:

{
    
    
	"versions": [
		{
    
    
			"ver": "1.0",
			"url": "http://127.0.0.1:5544/ResVers/Ver1.0.zip",
			"content": "基础版本的更新内容"
		},
		{
    
    
			"ver": "1.1",
			"url": "http://127.0.0.1:5544/ResVers/Ver1.1.zip",
			"content": "更新了登录界面的面板文字,更新了登录场景的的模型运动,"
		},
		{
    
    
			"ver": "1.2",
			"url": "http://127.0.0.1:5544/ResVers/Ver1.2.zip",
			"content": "更新了登录场景的的Cube模型上下运动,增多了场景中的球体和Cube。"
		}
	]
}

程序本地的版本为:

{
    
    "version":"1.1"}

运行效果

更新前:
在这里插入图片描述

更新后:
在这里插入图片描述

源码地址

https://download.csdn.net/download/qq_33789001/85056303

打不开说明暂未通过审核

坑点

目前使用的7z打包出来的*.7z文件ICSharpCode.SharpZipLib无法解压,这里打包时需要设置压缩格式:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_33789001/article/details/123852424
今日推荐