手游热更新那点事

整个包体如何刚刚安装打开的时候不要对游戏资源解压也可以支持热更新的功能,大家都知道大部分游戏打开的时候都是需要解压游戏资源(这个过程不消耗流量),比如王者荣耀,阴阳师这些游戏。其实这个就是Application.streamingAssetsPath的资源转移到沙盒路径上(Application.persistentDataPath),为什么需要转移资源呢?因为Application.streamingAssetsPath这个路径只支持读取,不支持写入,但是沙盒路径是可读可写的,所以需要将游戏资源转移到沙盒路径,然后资源有变换的话,就可以随便的替换。示范代码如下:

IEnumerator OnFirstExtract()
    {
        string dataPath = Util.DataPath;      //数据目录
        string resPath = Util.AppContentPath; //游戏包资源目录

        string fileIndex = resPath + AppConst.FileTxt;
        string outFileIndex = dataPath + AppConst.FileTxt;
        if (Directory.Exists(dataPath))
            Directory.Delete(dataPath, true);
        Directory.CreateDirectory(dataPath);
        //复制出files.txt
        if (Application.platform == RuntimePlatform.Android)
        {
            WWW www = new WWW(fileIndex);
            yield return www;

            if (www.isDone)
            {
                File.WriteAllBytes(outFileIndex, www.bytes);
            }
            yield return 0;
        }
        else File.Copy(fileIndex, outFileIndex, true);
        yield return new WaitForEndOfFrame();

        //TODO复制出启动界面(急需加载,首先复制)
        string infile = string.Empty;
        string outfile = string.Empty;
        string[] files = File.ReadAllLines(outFileIndex);
        foreach (var file in files)
        {
            if (!file.Contains(AppConst.FirstBundle))
                continue;
            infile = resPath + file;
            outfile = dataPath + file;
            Debug.Log("正在解包文件:>" + infile);
            string dir = Path.GetDirectoryName(outfile);
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
            if (Application.platform == RuntimePlatform.Android)
            {
                WWW www = new WWW(infile);
                yield return www;

                if (www.isDone)
                {
                    File.WriteAllBytes(outfile, www.bytes);
                }
                yield return 0;
            }
            else
            {
                if (File.Exists(outfile))
                {
                    File.Delete(outfile);
                }
                File.Copy(infile, outfile, true);
            }
            yield return new WaitForEndOfFrame();
        }
        GameObject page = ViewManager.vManager.ShowStart(ResPath.ViewName.StartUpView);
        yield return new WaitForSeconds(1f);
        int all = files.Length;
        int num = 0;
        //转移剩余ab包资源
        foreach (var file in files)
        {
            if (file.Contains(AppConst.FirstBundle))
                continue;
            infile = resPath + file;
            outfile = dataPath + file;
            Debug.Log("正在解包文件:>" + infile);
            string dir = Path.GetDirectoryName(outfile);
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
            if (Application.platform == RuntimePlatform.Android)
            {
                WWW www = new WWW(infile);
                yield return www;

                if (www.isDone)
                {
                    File.WriteAllBytes(outfile, www.bytes);
                }
                yield return 0;
            }
            else
            {
                if (File.Exists(outfile))
                {
                    File.Delete(outfile);
                }
                File.Copy(infile, outfile, true);
            }
            num++;
            page.GetComponent<StartUpBehavior>().ProgressUp(num*100/all);
            yield return new WaitForSeconds(0.5f);
        }
        page.GetComponent<StartUpBehavior>().ProgressUp(100);
        yield return new WaitForSeconds(0.1f);
        gameObject.AddComponent<GameManager>();
        gameObject.AddComponent<ViewManager>();
        Destroy(this);
    }

至于在解压的时候中途退出怎么办呢?可以使用Unity的PlayerPrefs.GetInt(),如果PlayerPrefs.GetInt("start_up")== 0的话表示资源没有解压完毕,如果资源全部解压就PlayerPrefs.SetInt("start_up",1),这样就知道在解压没有完毕的时候中途退出了。但是呢,能不能不解压直接进入游戏呢,其实思考了一下也是可以做到的,如下图:

首次启动游戏先把汇总文件迁移过去,然后生成汇总文件的秘钥,如果汇总文件版本一致就不需要单个检查了,如果对不上就到服务器下载新的汇总文件,然后去一个一个的比对文件秘钥,检查热更新的时候,如果优先级最高的路径有资源,这样此路径资源MD5和服务器的MD5比对,如果优先级最高的路径没有这个资源,就使用备用资源路径的MD5值,注意事项(沙盒路径是可以使用File,Directory这些API的,但是Application.streamingAssetsPath这个路径是不允许使用File,Directory这些API的,因为Application.streamingAssetsPath不是一个绝对路径),之后如果资源发现更新的,就下载到沙盒目录。资源加载的使用先去判断沙盒是否存在资源(File.Exists()),不存在的话就去加载备用路径的资源,这样首次启动游戏就不需要解压游戏资源了。

发布了26 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/m0_37920739/article/details/89215693