Unity3d StreamingAssets资源复制到沙盒

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity3d StreamingAssets资源复制到沙盒相关的知识,希望对你有一定的参考价值。

  由于项目已实现热更新,所以资源优先由沙盒读取,或完全直接从沙盒读取。为了防止在更新大版本时使用到旧项目的资源,所以需要对沙盒中旧的资源进行覆盖。

暂时实现了以下两种copy方案。


MD5文件格式与生成:


方法一:将本地资源一次性全部copy到沙盒,仅在首次安装或覆盖安装时对比oldfiles进行筛选覆盖

缺点:很慢。 30m资源耗时近20s,可优化:文件压缩后copy过去再解压。该方案暂时不用,仅做参考


  private string oldfilesName = "oldfiles.txt";

  private string filesName = "files.txt";


  IEnumerator CopyFolder()

    {

        List<FileInfo> localInfos = new List<FileInfo>();

        List<FileInfo> shaheInfos = new List<FileInfo>();

        List<FileInfo> copyInfos = new List<FileInfo>();


        //本地oldfiles

        string src = getStreamingPath_for_www() + oldfilesName;

        WWW www = new WWW(src);

        yield return www;

        if (!string.IsNullOrEmpty(www.error))

        {

            Debug.Log("www.error:" + www.error);

        }

        else

        {

            StringReader reader = new StringReader(www.text);

            string line;

            while ((line = reader.ReadLine()) != null)

            {

                string[] temp = line.Split(‘|‘);

                string fileName = temp[0];

                string md5 = temp[1];

                int length = int.Parse(temp[2]);

                FileInfo info;

                info.fileName = fileName;

                info.md5 = md5;

                info.length = length;

                localInfos.Add(info);

            }

            reader.Dispose();

            reader.Close();

        }

        www.Dispose();


        if (localInfos.Count > 0)

        {

            //沙盒oldfiles

            string des = Application.persistentDataPath + "/" + oldfilesName;

            if (File.Exists(des))

            {

                StreamReader reader = File.OpenText(des);

                string line;

                while ((line = reader.ReadLine()) != null)

                {

                    string[] temp = line.Split(‘|‘);

                    string fileName = temp[0];

                    string md5 = temp[1];

                    int length = int.Parse(temp[2]);

                    FileInfo info;

                    info.fileName = fileName;

                    info.md5 = md5;

                    info.length = length;

                    shaheInfos.Add(info);

                }

                reader.Dispose();

                reader.Close();

            }


            //需要更新oldfiles

            copyInfos = CompareFileInfo(localInfos, shaheInfos);

            foreach (var item in copyInfos)

            {

                //string  mfileName = item.fileName.Replace("\\","/");

                string _src = getStreamingPath_for_www() + item.fileName;

                string fileName = item.fileName.Substring(item.fileName.LastIndexOf(‘/‘) + 1);

                string _des = Application.persistentDataPath + "/" + fileName;

                //Debug.Log("des:" + _des);

                //Debug.Log("src:" + _src);

                WWW _www = new WWW(_src);

                yield return _www;

                if (!string.IsNullOrEmpty(_www.error))

                {

                    Debug.Log("_www.error:" + _www.error);

                }

                else

                {

                    FileStream stream = new FileStream(_des, FileMode.Create);

                    stream.Write(_www.bytes, 0, _www.bytes.Length);

                    stream.Flush();

                    stream.Close();


                }

                _www.Dispose();

            }


            if (copyInfos.Count > 0)

            {

                //copy oldfiles

                StartCoroutine(copy(oldfilesName));


                //删除 file 和 version 

                //删除这两个文件是copy完之后让游戏重新进行一次热更新,以保证沙盒资                  源与资源服资源保持一致(也是避免新资源被copy而报错)

                string filepath = Application.persistentDataPath + "/files.txt";

                string versionpath = Application.persistentDataPath + "/Version";

                if (File.Exists(filepath))

                {

                    File.Delete(filepath);

                }

                if (File.Exists(versionpath))

                {

                    File.Delete(versionpath);

                }

            }


            Debug.logger.Log("文件复制完成:共" + copyInfos.Count + "个文件");

        }

        else

        {

            Debug.logger.Log("本地无文件:" + copyInfos.Count + "个文件");

        }


        StartCoroutine(compareVersion());


    }



    /// <summary>  

    /// 将streaming path 下的文件copy到对应用  

    /// 

    IEnumerator copy(string fileName)

    {

        string src = getStreamingPath_for_www() + fileName;

        string des = Application.persistentDataPath + "/" + fileName;

        //Debug.Log("des:" + des);

        //Debug.Log("src:" + src);

        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();

    }




    //比较md5

    List<FileInfo> CompareFileInfo(List<FileInfo> localInfos, List<FileInfo> shaheInfos)

    {

        List<FileInfo> downloadList = new List<FileInfo>();

        for (int i = 0; i < localInfos.Count; i++)

        {

            FileInfo info = localInfos[i];

            bool flag = NeedCopy(info.fileName, info.md5, shaheInfos);

            if (flag)

            {

                downloadList.Add(info);

            }

        }

        return downloadList;

    }


    //true 需要下载,false 不用下载

    bool NeedCopy(string fileName, string md5, List<FileInfo> shaheInfos)

    {

        for (int i = 0; i < shaheInfos.Count; i++)

        {

            if (shaheInfos[i].fileName == fileName)

            {

                if (shaheInfos[i].md5 == md5)

                {

                    return false;

                }

                else

                {

                    return true;

                }

            }

        }

        return true;

    }


    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;

    }


    string getPersistentPath_for_www()

    {

        string pre = "file://";

#if UNITY_EDITOR || UNITY_STANDALONE_WIN

        pre = "file:///";

#elif UNITY_ANDROID  

        pre = "file://";  

#elif UNITY_IPHONE  

        pre = "file://";  

#endif

        string path = pre + Application.persistentDataPath + "/";

        return path;

    }


    #endregion 


方法二、仅copy覆盖沙盒中存在的旧资源

本文出自 “wo爱钱” 博客,请务必保留此出处http://mozhenrui.blog.51cto.com/11845221/1936625

以上是关于Unity3d StreamingAssets资源复制到沙盒的主要内容,如果未能解决你的问题,请参考以下文章

请教unity3d 在ios上资源路径的问题

unity3d unity5.0 assetbundlemanifest包含哪些数据

unity3d中StreamingAssets和Resources目录的区别

19、StreamingAssets和Resources目录的区别

unity3d android 下无法读取StreamingAssets 文件 路径都对啊

Unity3d热更新之下载