yyl
2025-05-20 32cebcf8e28159ace19b3d4778edba04607930b4
搬运流程
3个文件已修改
35个文件已添加
2787 ■■■■■ 已修改文件
Main/Common/SevenZip.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Common/SevenZip/lzma.cs 873 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Common/SevenZip/lzma.cs.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/AssetCopyTask.cs 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/AssetCopyTask.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/AssetDeCompressTask.cs 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/AssetDeCompressTask.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/BuiltInAssetCopyTask.cs 249 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/BuiltInAssetCopyTask.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/CheckAssetValidTask.cs 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/CheckAssetValidTask.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/DownLoadAssetTask.cs 277 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/DownLoadAssetTask.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/GetVersionInfoTask.cs 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/GetVersionInfoTask.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/InitSettingTask.cs 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/InitSettingTask.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/LaunchInHot.cs 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/LaunchInHot.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/LaunchProgressInfo.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/LaunchProgressInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/LaunchStage.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/LaunchStage.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/LaunchTask.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/LaunchTask.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/RequestPermissionStart.cs 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/RequestPermissionStart.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/SDKInitedTask.cs 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Launch/SDKInitedTask.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/GameEngine/Login.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Manager/ResManager.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Manager/StageManager.cs 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/ResModule/AssetBundle/AssetBundleUtility.cs 77 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/SevenZipUtility.cs 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/SevenZipUtility.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/ShaderUtility.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/ShaderUtility.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Common/SevenZip.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 00dea6db89fa7bf48906e1612fbf177e
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Common/SevenZip/lzma.cs
New file
@@ -0,0 +1,873 @@
#if !(UNITY_IOS || UNITY_IPHONE)
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using System.Collections.Generic;
using System.IO;
#if (UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1) && !UNITY_EDITOR
 using File = UnityEngine.Windows.File;
#else
using File = System.IO.File;
#endif
#if NETFX_CORE
#if UNITY_WSA_10_0
        using System.IO.IsolatedStorage;
        using static System.IO.Directory;
        using static System.IO.File;
        using static System.IO.FileStream;
#endif
#endif
public class lzma
{
    //if you want to be able to call the functions: get7zinfo, get7zSize, decode2Buffer from a thread set this string before to the Application.persistentDataPath !
    public static string persitentDataPath = "";
#if !(UNITY_WSA || UNITY_WP_8_1) || UNITY_EDITOR
    internal static int[] props = new int[7];
    internal static bool defaultsSet = false;
    //0 = level, /* 0 <= level <= 9, default = 5 */
    //1 = dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
    //2 = lc, /* 0 <= lc <= 8, default = 3  */
    //3 = lp, /* 0 <= lp <= 4, default = 0  */
    //4 = pb, /* 0 <= pb <= 4, default = 2  */
    //5 = fb,  /* 5 <= fb <= 273, default = 32 */
    //6 = numThreads /* 1 or 2, default = 2 */
    //A function that sets the compression properties for the lzma compressor. Will affect the lzma alone file and the lzma buffer compression.
    //A simple usage of this function is to call it only with the 1st parameter that sets the compression level: setProps(9);
    //
    //Multithread safe advice: call this function before starting any thread operations !!!
    public static void setProps(int level = 5, int dictSize = 16777216, int lc = 3, int lp = 0, int pb = 2, int fb = 32, int numThreads = 2)
    {
        defaultsSet = true;
        props[0] = level;
        props[1] = dictSize;
        props[2] = lc;
        props[3] = lp;
        props[4] = pb;
        props[5] = fb;
        props[6] = numThreads;
    }
#endif
#if (UNITY_WEBGL) && !UNITY_EDITOR
#if (!UNITY_WEBGL)
            [DllImport("__Internal")]
            public static extern int lsetPermissions(string filePath, string _user, string _group, string _other);
            [DllImport("__Internal")]
            private static extern int decompress7zip(string filePath, string exctractionPath, bool fullPaths,  string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
#endif
        [DllImport("__Internal")]
        private static extern int decompress7zip2(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("__Internal")]
        private static extern int _getSize(string filePath, string tempPath, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("__Internal")]
        internal static extern int lzmaUtil(bool encode, string inPath, string outPath, IntPtr Props);
        [DllImport("__Internal")]
        internal static extern int decode2Buf(string filePath, string entry,  IntPtr buffer, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("__Internal")]
        internal static extern void _releaseBuffer(IntPtr buffer);
        [DllImport("__Internal")]
        internal static extern IntPtr Lzma_Compress( IntPtr buffer, int bufferLength, bool makeHeader, ref int v, IntPtr Props);
        [DllImport("__Internal")]
        internal static extern int Lzma_Uncompress( IntPtr buffer, int bufferLength, int uncompressedSize,  IntPtr outbuffer,bool useHeader);
#endif
#if UNITY_5_4_OR_NEWER
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX) && (!UNITY_EDITOR || UNITY_EDITOR_LINUX)
        private const string libname = "lzma";
#elif UNITY_EDITOR || UNITY_STANDALONE_WIN
    private const string libname = "liblzma";
#endif
#else
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX) && !UNITY_EDITOR
        private const string libname = "lzma";
#endif
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
        private const string libname = "liblzma";
#endif
#endif
#if UNITY_EDITOR || UNITY_STANDALONE_WIN ||  UNITY_ANDROID || UNITY_STANDALONE_LINUX
#if ( UNITY_STANDALONE_LINUX || UNITY_ANDROID ||  UNITY_EDITOR_LINUX) && !UNITY_EDITOR_WIN
            //set permissions of a file in user, group, other. Each string should contain any or all chars of "rwx".
            //returns 0 on success
            [DllImport(libname, EntryPoint = "lsetPermissions")]
            internal static extern int lsetPermissions(string filePath, string _user, string _group, string _other);
#endif
    [DllImport(libname, EntryPoint = "decompress7zip")]
    internal static extern int decompress7zip(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
    [DllImport(libname, EntryPoint = "decompress7zip2")]
    internal static extern int decompress7zip2(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
    [DllImport(libname, EntryPoint = "_getSize")]
    internal static extern int _getSize(string filePath, string tempPath, IntPtr FileBuffer, int FileBufferLength);
    [DllImport(libname, EntryPoint = "lzmaUtil")]
    internal static extern int lzmaUtil(bool encode, string inPath, string outPath, IntPtr Props);
    [DllImport(libname, EntryPoint = "decode2Buf")]
    internal static extern int decode2Buf(string filePath, string entry, IntPtr buffer, IntPtr FileBuffer, int FileBufferLength);
    [DllImport(libname, EntryPoint = "_releaseBuffer")]
    internal static extern void _releaseBuffer(IntPtr buffer);
    [DllImport(libname, EntryPoint = "Lzma_Compress")]
    internal static extern IntPtr Lzma_Compress(IntPtr buffer, int bufferLength, bool makeHeader, ref int v, IntPtr Props);
    [DllImport(libname, EntryPoint = "Lzma_Uncompress")]
    internal static extern int Lzma_Uncompress(IntPtr buffer, int bufferLength, int uncompressedSize, IntPtr outbuffer, bool useHeader);
#endif
#if (UNITY_WP_8_1 || UNITY_WSA) && !UNITY_EDITOR
#if UNITY_WSA_10_0
            [DllImport("liblzma", EntryPoint = "decompress7zip")]
            internal static extern int decompress7zip(string filePath, string exctractionPath, bool fullPaths,  string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
#endif
        [DllImport("liblzma", EntryPoint = "decompress7zip2")]
        internal static extern int decompress7zip2(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("liblzma", EntryPoint = "_getSize")]
        internal static extern int _getSize(string filePath, string tempPath, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("liblzma", EntryPoint = "decode2Buf")]
        internal static extern int decode2Buf(string filePath, string entry,  IntPtr buffer, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("liblzma", EntryPoint = "Lzma_Uncompress")]
        internal static extern int Lzma_Uncompress( IntPtr buffer, int bufferLength, int uncompressedSize, IntPtr outbuffer,bool useHeader);
#endif
    // set permissions of a file in user, group, other.
    // Each string should contain any or all chars of "rwx".
    // returns 0 on success
    public static int setFilePermissions(string filePath, string _user, string _group, string _other)
    {
#if (UNITY_STANDALONE_LINUX || UNITY_ANDROID ||  UNITY_EDITOR_LINUX) && !UNITY_EDITOR_WIN
            return lsetPermissions(filePath, _user, _group, _other);
#else
        return -1;
#endif
    }
    // An integer variable to store the total number of files in a 7z archive, excluding the folders.
    public static int trueTotalFiles = 0;
    //ERROR CODES:
    //  1 : OK
    //    2 : Could not find requested file in archive
    // -1 : Could not open input(7z) file
    // -2 : Decoder doesn't support this archive
    // -3 : Can not allocate memory
    // -4 : CRC error of 7z file
    // -5 : Unknown error
    // -6 : Can not open output file (usually when the path to write to, is invalid)
    // -7 : Can not write output file
    // -8 : Can not close output file
    //The most common use of this library is to download a 7z file in your Application.persistentDataPath directory
    //and decompress it in a folder that you want.
    //int lz=lzma.doDecompress7zip(Application.persistentDataPath+"/myCompresedFile.7z",Application.persistentDataPath+"/myUncompressedFiles/");
    //WSA8.1 does not support large files.
    //filePath            : the full path to the archive, including the archives name. (/myPath/myArchive.7z)
    //exctractionPath    : the path in where you want your files to be extracted
    //progress          : a single item integer array to get the progress of the extracted files (use this function when calling from a separate thread, otherwise call the 2nd implementation)
    //                  : (for ios this integer is not properly updated. So we use the lzma.getProgressCount() function to get the progress. See example.)
    //largeFiles        : set this to true if you are extracting files larger then 30-40 Mb. It is slower though but prevents crashing your app when extracting large files!
    //fullPaths            : set this to true if you want to keep the folder structure of the 7z file.
    //entry                : set the name of a single file file you want to extract from your archive. If the file resides in a folder, the full path should be added.
    //                       (for example  game/meshes/small/table.mesh )
    //FileBuffer        : A buffer that holds a 7zip file. When assigned the function will decompress from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX)
    //use this function from a separate thread to get the progress  of the extracted files in the referenced 'progress' integer.
    //
    public static int doDecompress7zip(string filePath, string exctractionPath, int[] progress, bool largeFiles = false, bool fullPaths = false, string entry = null, byte[] FileBuffer = null)
    {
        int res = 0;
        GCHandle ibuf = GCHandle.Alloc(progress, GCHandleType.Pinned);
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN
        if(FileBuffer != null) {
            GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned);
            if (largeFiles){
                res = decompress7zip(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , fbuf.AddrOfPinnedObject(), FileBuffer.Length);
            }else{
                res =  decompress7zip2(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , fbuf.AddrOfPinnedObject(), FileBuffer.Length);
            }
                fbuf.Free(); ibuf.Free(); return res;
        } else {
            if (largeFiles){
                res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , IntPtr.Zero, 0);
                ibuf.Free(); return res;
            }else{
                res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , IntPtr.Zero, 0);
                ibuf.Free(); return res;
            }
        }
#endif
#if (!UNITY_WSA && !UNITY_WEBGL && !UNITY_STANDALONE_LINUX && !UNITY_ANDROID) || UNITY_EDITOR_WIN || UNITY_WSA_10_0
        if (largeFiles)
        {
            res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
        }
        else
        {
            res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
        }
#endif
#if (UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1 || UNITY_WEBGL) && !UNITY_EDITOR
            res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
#endif
    }
    //same as above only the progress integer is a local variable.
    //use this when you don't want to get the progress of the extracted files and when not calling the function from a separate thread.
    public static int doDecompress7zip(string filePath, string exctractionPath, bool largeFiles = false, bool fullPaths = false, string entry = null, byte[] FileBuffer = null)
    {
        //make a check if the last '/' exists at the end of the exctractionPath and add it if it is missing
        if (@exctractionPath.Substring(@exctractionPath.Length - 1, 1) != "/") { @exctractionPath += "/"; }
        int[] progress = new int[1];
        GCHandle ibuf = GCHandle.Alloc(progress, GCHandleType.Pinned);
        int res = 0;
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN
        if(FileBuffer != null) {
            GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned);
            if (largeFiles){
                res = decompress7zip(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), fbuf.AddrOfPinnedObject(), FileBuffer.Length);
            }else{
                res = decompress7zip2(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), fbuf.AddrOfPinnedObject(), FileBuffer.Length);
            }
                fbuf.Free(); ibuf.Free(); return res;
        } else {
            if (largeFiles){
                res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
                ibuf.Free(); return res;
            }else{
                res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
                ibuf.Free(); return res;
            }
        }
#endif
#if (!UNITY_WSA && !UNITY_WEBGL && !UNITY_STANDALONE_LINUX && !UNITY_ANDROID) || UNITY_EDITOR_WIN || UNITY_WSA_10_0
        if (largeFiles)
        {
            res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
        }
        else
        {
            res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
        }
#endif
#if (UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1 || UNITY_WEBGL) && !UNITY_EDITOR
            res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
#endif
    }
#if !(UNITY_WSA || UNITY_WP_8_1) || UNITY_EDITOR
    //ERROR CODES (for both encode/decode LzmaUtil functions):
    //   1 : OK
    // -10 : Can not read input file
    // -11 : Can not write output file
    // -12 : Can not allocate memory
    // -13 : Data error
    //This function encodes a single archive in lzma alone format.
    //inPath    : the file to be encoded. (use full path + file name)
    //outPath    : the .lzma file that will be produced. (use full path + file name)
    //
    //You can set the compression properties by calling the setProps function before.
    //setProps(9) for example will set compression evel to highest level.
    public static int LzmaUtilEncode(string inPath, string outPath)
    {
        if (!defaultsSet) setProps();
        GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned);
        int res = lzmaUtil(true, @inPath, @outPath, prps.AddrOfPinnedObject());
        prps.Free();
        return res;
    }
    //This function decodes a single archive in lzma alone format.
    //inPath    : the .lzma file that will be decoded. (use full path + file name)
    //outPath    : the decoded file. (use full path + file name)
    public static int LzmaUtilDecode(string inPath, string outPath)
    {
        return lzmaUtil(false, @inPath, @outPath, IntPtr.Zero);
    }
#endif
    //Lists get filled with filenames (including path if the file is in a folder) and uncompressed file sizes
    public static List<string> ninfo = new List<string>();//filenames
    public static List<long> sinfo = new List<long>();//file sizes
    //this function fills the ArrayLists with the filenames and file sizes that are in the 7zip file
    //returns            : the total size in bytes of the files in the 7z archive
    //
    //filePath            : the full path to the archive, including the archives name. (/myPath/myArchive.7z)
    //tempPath            : (optional) a temp path that will be used to write the files info (otherwise the path of the 7z archive will be used)
    //                    : this is useful when your 7z archive resides in a read only location.
    //                    : the tempPath should be in this form: 'dir/dir/myTempLog' with no slash in the end. The last name will be used as the log's filename.
    //FileBuffer        : A buffer that holds a 7zip file. When assigned the function will read from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX)
    //
    //trueTotalFiles is an integer variable to store the total number of files in a 7z archive, excluding the folders.
    public static long get7zInfo(string filePath, string tempPath = null, byte[] FileBuffer = null)
    {
        ninfo.Clear(); sinfo.Clear();
        trueTotalFiles = 0;
        int res = -1;
        string logPath = "";
#if !NETFX_CORE
        if (@tempPath == null)
        {
            if (persitentDataPath.Length > 0) logPath = @persitentDataPath + "/sevenZip.log"; else logPath = @Application.persistentDataPath + "/sevenZip.log";
        }
        else { logPath = @tempPath; }
#endif
        //for WSA, logPath should always be: Application.persistentDataPath + "/sevenZip.log";
#if NETFX_CORE
#if UNITY_WSA_10_0
                if(persitentDataPath.Length>0) logPath = @persitentDataPath + "/sevenZip.log"; else  logPath = @Application.persistentDataPath + "/sevenZip.log";
#endif
#if UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1
                if(persitentDataPath.Length>0) logPath = @persitentDataPath + "/sevenZip.log"; else  logPath = @UnityEngine.Windows.Directory.localFolder + "/sevenZip.log";
#endif
#endif
        if (File.Exists(logPath + ".txt")) File.Delete(logPath + ".txt");
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN
          if(FileBuffer != null) {
                GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned);
                res = _getSize(null, logPath,  fbuf.AddrOfPinnedObject(), FileBuffer.Length);
                fbuf.Free();
            }else {
                res = _getSize(@filePath, logPath,  IntPtr.Zero, 0);
            }
#else
        res = _getSize(@filePath, logPath, IntPtr.Zero, 0);
#endif
        if (res == -1) { /*Debug.Log("Input file not found.");*/ return -1; }
        if (!File.Exists(logPath + ".txt")) {/* Debug.Log("Info file not found.");*/ return -3; }
#if !NETFX_CORE
        StreamReader r = new StreamReader(logPath + ".txt");
#endif
#if NETFX_CORE
#if UNITY_WSA_10_0
            IsolatedStorageFile ipath = IsolatedStorageFile.GetUserStoreForApplication();
            StreamReader r = new StreamReader(new IsolatedStorageFileStream("sevenZip.log.txt", FileMode.Open, ipath));
#endif
#if UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1
            var data = UnityEngine.Windows.File.ReadAllBytes(logPath + ".txt");
            string ss = System.Text.Encoding.UTF8.GetString(data,0,data.Length);
            StringReader r = new StringReader(ss);
#endif
#endif
        string line;
        string[] rtt;
        long t = 0, sum = 0;
        while ((line = r.ReadLine()) != null)
        {
            rtt = line.Split('|');
            ninfo.Add(rtt[0]);
            long.TryParse(rtt[1], out t);
            sum += t;
            sinfo.Add(t);
            if (t > 0) trueTotalFiles++;
        }
#if !NETFX_CORE
        r.Close();
#endif
        r.Dispose();
        File.Delete(logPath + ".txt");
        return sum;
    }
    //this function returns the uncompressed file size of a given file in the 7z archive if specified,
    //otherwise it will return the total uncompressed size of all the files in the archive.
    //
    //If you don't fill the filePath parameter it will assume that the get7zInfo function has already been called.
    //
    //
    //filePath            : the full path to the archive, including the archives name. (/myPath/myArchive.7z)
    //                     : if you call the function with filePath as null, it will try to find file sizes from the last call.
    //fileName             : the file name we want to get the file size (if it resides in a folder add the folder path also)
    //tempPath            : (optional) a temp path that will be used to write the files info (otherwise the path of the 7z archive will be used)
    //                    : this is useful when your 7z archive resides in a read only location.
    //                    : the tempPath should be in this form: 'dir/dir/myTempLog' with no slash in the end. The last name will be used as the log's filename.
    //FileBuffer        : A buffer that holds a 7zip file. When assigned the function will read from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX)
    public static long get7zSize(string filePath = null, string fileName = null, string tempPath = null, byte[] FileBuffer = null)
    {
        if (filePath != null)
        {
            if (get7zInfo(@filePath, @tempPath, FileBuffer) < 0) { return -1; }
        }
        if (ninfo == null)
        {
            if (ninfo.Count == 0) { return -1; }
        }
        long sum = 0;
        if (fileName != null)
        {
            for (int i = 0; i < ninfo.Count; i++)
            {
                if (ninfo[i].ToString() == fileName)
                {
                    return (long)sinfo[i];
                }
            }
        }
        else
        {
            for (int i = 0; i < ninfo.Count; i++)
            {
                sum += (long)sinfo[i];
            }
            return sum;
        }
        return -1;//nothing was found
    }
    //A function to decode a specific archive in a 7z archive to a byte buffer
    //
    //filePath        : the full path to the 7z archive
    //entry            : the file name to decode to a buffer. If the file resides in a folder, the full path should be used.
    //tempPath        : (optional) a temp path that will be used to write the files info (otherwise the path of the 7z archive will be used)
    //                : this is useful when your 7z archive resides in a read only location.
    //                : the tempPath should be in this form: 'dir/dir/myTempLog' with no slash in the end. The last name will be used as the log's filename.
    //FileBuffer    : A buffer that holds a 7zip file. When assigned the function will read from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX)
    public static byte[] decode2Buffer(string filePath, string entry, string tempPath = null, byte[] FileBuffer = null)
    {
        int bufs = (int)get7zSize(@filePath, entry, @tempPath, FileBuffer);
        if (bufs <= 0) return null;//entry error or it does not exist
        byte[] nb = new byte[bufs];
        int res = 0;
        GCHandle dec2buf = GCHandle.Alloc(nb, GCHandleType.Pinned);
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN
          if(FileBuffer != null) {
                GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned);
                res = decode2Buf(null, entry, dec2buf.AddrOfPinnedObject(), fbuf.AddrOfPinnedObject(), FileBuffer.Length);
                fbuf.Free();
            }else {
                res = decode2Buf(@filePath, entry, dec2buf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            }
#else
        res = decode2Buf(@filePath, entry, dec2buf.AddrOfPinnedObject(), IntPtr.Zero, 0);
#endif
        dec2buf.Free();
        if (res == 1) { return nb; }
        else { nb = null; return null; }
    }
#if !(UNITY_WSA || UNITY_WP_8_1) || UNITY_EDITOR
    //This function encodes inBuffer to lzma alone format into the outBuffer provided.
    //The buffer can be saved also into a file and can be opened by applications that opens the lzma alone format.
    //This buffer can be uncompressed by the decompressBuffer function.
    //Returns true if success
    //if makeHeader==false then the lzma 13 bytes header will not be added to the buffer.
    //
    //You can set the compression properties by calling the setProps function before.
    //setProps(9) for example will set compression level to the highest level.
    //
    public static bool compressBuffer(byte[] inBuffer, ref byte[] outBuffer, bool makeHeader = true)
    {
        if (!defaultsSet) setProps();
        GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned);
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        IntPtr ptr;
        int res = 0;
        ptr = Lzma_Compress(cbuf.AddrOfPinnedObject(), inBuffer.Length, makeHeader, ref res, prps.AddrOfPinnedObject());
        cbuf.Free(); prps.Free();
        if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return false; }
        Array.Resize(ref outBuffer, res);
        Marshal.Copy(ptr, outBuffer, 0, res);
        _releaseBuffer(ptr);
        return true;
    }
    //same as the above function, only it compresses a part of the input buffer.
    //
    //inBufferPartialLength: the size of the input buffer that should be compressed
    //inBufferPartialIndex:  the offset of the input buffer from where the compression will start
    //
    public static bool compressBufferPartial(byte[] inBuffer, int inBufferPartialIndex, int inBufferPartialLength, ref byte[] outBuffer, bool makeHeader = true)
    {
        if (inBufferPartialIndex + inBufferPartialLength > inBuffer.Length) return false;
        if (!defaultsSet) setProps();
        GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned);
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        IntPtr ptr;
        IntPtr ptrPartial;
        int res = 0;
        ptrPartial = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + inBufferPartialIndex);
        ptr = Lzma_Compress(ptrPartial, inBufferPartialLength, makeHeader, ref res, prps.AddrOfPinnedObject());
        cbuf.Free();
        if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return false; }
        Array.Resize(ref outBuffer, res);
        Marshal.Copy(ptr, outBuffer, 0, res);
        _releaseBuffer(ptr);
        return true;
    }
    //same as compressBufferPartial, only this function will compress the data into a fixed size buffer
    //the compressed size is returned so you can manipulate it at will.
    public static int compressBufferPartialFixed(byte[] inBuffer, int inBufferPartialIndex, int inBufferPartialLength, ref byte[] outBuffer, bool safe = true, bool makeHeader = true)
    {
        if (inBufferPartialIndex + inBufferPartialLength > inBuffer.Length) return 0;
        if (!defaultsSet) setProps();
        GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned);
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        IntPtr ptr;
        IntPtr ptrPartial;
        int res = 0;
        ptrPartial = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + inBufferPartialIndex);
        ptr = Lzma_Compress(ptrPartial, inBufferPartialLength, makeHeader, ref res, prps.AddrOfPinnedObject());
        cbuf.Free();
        if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return 0; }
        //if the compressed buffer is larger then the fixed size buffer we use:
        //1. then write only the data that fit in it.
        //2. or we return 0.
        //It depends on if we set the safe flag to true or not.
        if (res > outBuffer.Length)
        {
            if (safe) { _releaseBuffer(ptr); return 0; } else { res = outBuffer.Length; }
        }
        Marshal.Copy(ptr, outBuffer, 0, res);
        _releaseBuffer(ptr);
        return res;
    }
    //same as the compressBuffer function, only this function will put the result in a fixed size buffer to avoid memory allocations.
    //the compressed size is returned so you can manipulate it at will.
    public static int compressBufferFixed(byte[] inBuffer, ref byte[] outBuffer, bool safe = true, bool makeHeader = true)
    {
        if (!defaultsSet) setProps();
        GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned);
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        IntPtr ptr;
        int res = 0;
        ptr = Lzma_Compress(cbuf.AddrOfPinnedObject(), inBuffer.Length, makeHeader, ref res, prps.AddrOfPinnedObject());
        cbuf.Free(); prps.Free();
        if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return 0; }
        //if the compressed buffer is larger then the fixed size buffer we use:
        //1. then write only the data that fit in it.
        //2. or we return 0.
        //It depends on if we set the safe flag to true or not.
        if (res > outBuffer.Length)
        {
            if (safe) { _releaseBuffer(ptr); return 0; } else { res = outBuffer.Length; }
        }
        Marshal.Copy(ptr, outBuffer, 0, res);
        _releaseBuffer(ptr);
        return res;
    }
#endif
    //This function will decompress a compressed asset bundle.
    //It finds the magic number of the lzma format and extracts from there.
    //
    //inBuffer:        the buffer that stores a compressed asset bundle.
    //outBuffer:    a referenced buffer where the asset bundle will be uncompressed.
    //The error codes
    /*
        OK 0
        ERROR_DATA 1
        ERROR_MEM 2
        ERROR_UNSUPPORTED 4
        ERROR_PARAM 5
        ERROR_INPUT_EOF 6
        ERROR_OUTPUT_EOF 7
        ERROR_FAIL 11
        ERROR_THREAD 12
    */
    public static int decompressAssetBundle(byte[] inBuffer, ref byte[] outbuffer)
    {
        int offset = 0;
        for (int i = 0; i < inBuffer.Length; i++)
        {
            if (i > 1024) break;
            if (inBuffer[i] == 0x5d)
            {
                if (inBuffer[i + 1] == 0x00)
                {
                    if (inBuffer[i + 2] == 0x00)
                    {
                        if (inBuffer[i + 3] == 0x08)
                        {
                            offset = i; break;
                        }
                    }
                }
            }
        }
        if (offset == 0 || offset > 1024) return 4;
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        IntPtr ptrBundle = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + offset);
        int uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, offset + 5);
        if (uncompressedSize < 0) { cbuf.Free(); return 4; }
        Array.Resize(ref outbuffer, uncompressedSize);
        GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned);
        int res = Lzma_Uncompress(ptrBundle, inBuffer.Length - offset, uncompressedSize, obuf.AddrOfPinnedObject(), true);
        cbuf.Free();
        obuf.Free();
        //if(res!=0){/*Debug.Log("ERROR: "+res.ToString());*/ return res; }
        return res;
    }
    /*
    //this will decompress an lzma alone format file.
    public static  int decompressLzmaAlone(string inFile,  string outFile){
        if(File.Exists(inFile)) {
            var inBuffer = File.ReadAllBytes(inFile);
            int offset = 0;
            for(int i=0; i<inBuffer.Length; i++) {
                if(i>16) break;
                if(inBuffer[i] == 0x5d) {
                    if(inBuffer[i+1] == 0x00) {
                        if(inBuffer[i+2] == 0x00) {
                            if(inBuffer[i+3] == 0x00) {
                                offset = i;  break;
                            }
                        }
                    }
                }
            }
            if(offset>16) {  inBuffer=null; return 4; }
            GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
            IntPtr ptrBundle = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + offset);
            int uncompressedSize = (int)BitConverter.ToUInt64(inBuffer,offset+5);
            if(uncompressedSize<0) { cbuf.Free(); return 4; }
            byte[] outBuffer = new byte[uncompressedSize];
            GCHandle obuf = GCHandle.Alloc(outBuffer, GCHandleType.Pinned);
            int res = Lzma_Uncompress(ptrBundle, inBuffer.Length-offset, uncompressedSize, obuf.AddrOfPinnedObject(), true);
            cbuf.Free();
            obuf.Free();
            File.WriteAllBytes(outFile, outBuffer);
            Array.Resize(ref outBuffer, 0);
            Array.Resize(ref inBuffer, 0);
            outBuffer = null;
            inBuffer = null;
            GC.Collect();
            return res;
        } else {
            return -1;
        }
    }
    */
    //This function decompresses an lzma compressed byte buffer.
    //If the useHeader flag is false you have to provide the uncompressed size of the buffer via the customLength integer.
    //if res==0 operation was successful
    //The error codes
    /*
        OK 0
        ERROR_DATA 1
        ERROR_MEM 2
        ERROR_UNSUPPORTED 4
        ERROR_PARAM 5
        ERROR_INPUT_EOF 6
        ERROR_OUTPUT_EOF 7
        ERROR_FAIL 11
        ERROR_THREAD 12
        */
    public static int decompressBuffer(byte[] inBuffer, ref byte[] outbuffer, bool useHeader = true, int customLength = 0)
    {
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        int uncompressedSize = 0;
        //if the lzma header will be used to extract the uncompressed size of the buffer. If the buffer does not have a header
        //provide the known uncompressed size through the customLength integer.
        if (useHeader) uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, 5); else uncompressedSize = customLength;
        Array.Resize(ref outbuffer, uncompressedSize);
        GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned);
        int res = Lzma_Uncompress(cbuf.AddrOfPinnedObject(), inBuffer.Length, uncompressedSize, obuf.AddrOfPinnedObject(), useHeader);
        cbuf.Free();
        obuf.Free();
        //if(res!=0){/*Debug.Log("ERROR: "+res.ToString());*/ return res; }
        return res;
    }
    public static byte[] decompressBuffer(byte[] inBuffer, bool useHeader = true, int customLength = 0)
    {
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        int uncompressedSize = 0;
        //if the lzma header will be used to extract the uncompressed size of the buffer. If the buffer does not have a header
        //provide the known uncompressed size through the customLength integer.
        if (useHeader) uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, 5); else uncompressedSize = customLength;
        byte[] outbuffer = new byte[uncompressedSize];
        GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned);
        int res = Lzma_Uncompress(cbuf.AddrOfPinnedObject(), inBuffer.Length, uncompressedSize, obuf.AddrOfPinnedObject(), useHeader);
        cbuf.Free();
        obuf.Free();
        if (res != 0) {/*Debug.Log("ERROR: "+res.ToString());*/ return null; }
        return outbuffer;
    }
    //same as above function. Only this one outputs to a buffer of fixed which size isn't resized to avoid memory allocations.
    //The fixed buffer should have a size that will be able to hold the incoming decompressed data.
    //returns the uncompressed size.
    public static int decompressBufferFixed(byte[] inBuffer, ref byte[] outbuffer, bool safe = true, bool useHeader = true, int customLength = 0)
    {
        int uncompressedSize = 0;
        //if the lzma header will be used to extract the uncompressed size of the buffer. If the buffer does not have a header
        //provide the known uncompressed size through the customLength integer.
        if (useHeader) uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, 5); else uncompressedSize = customLength;
        //Check if the uncompressed size is bigger then the size of the fixed buffer. Then:
        //1. write only the data that fit in it.
        //2. or return a negative number.
        //It depends on if we set the safe flag to true or not.
        if (uncompressedSize > outbuffer.Length)
        {
            if (safe) return -101; else uncompressedSize = outbuffer.Length;
        }
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned);
        int res = Lzma_Uncompress(cbuf.AddrOfPinnedObject(), inBuffer.Length, uncompressedSize, obuf.AddrOfPinnedObject(), useHeader);
        cbuf.Free();
        obuf.Free();
        if (res != 0) {/*Debug.Log("ERROR: "+res.ToString());*/ return -res; }
        return uncompressedSize;
    }
}
#endif
Main/Common/SevenZip/lzma.cs.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 13c1c59b80961f74e9c2c894f0961517
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
Main/Core/GameEngine/Launch.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1a1192b48924f274e8e3ce3c265331a8
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/AssetCopyTask.cs
New file
@@ -0,0 +1,266 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class AssetCopyTask : LaunchTask
{
    int completedCount = 0;
    int totalCount = -1;
    List<FileInfo> copyTasks = new List<FileInfo>();
    public override float expectTime
    {
        get { return LocalSave.GetFloat("AssetCopyTask_ExpectTime", 70f); }
        protected set { LocalSave.SetFloat("AssetCopyTask_ExpectTime", value); }
    }
    public override void Begin()
    {
        LaunchInHot.m_CurrentStage = LaunchStage.AssetCopy;
        duration = Mathf.Max(0.5f, expectTime);
        outTime = 50f;
        if (Application.isEditor)
        {
            done = true;
        }
        else
        {
            switch (Application.platform)
            {
                case RuntimePlatform.Android:
                    AndroidCopyAsset();
                    break;
                case RuntimePlatform.IPhonePlayer:
                    IOSCopyAsset();
                    break;
                case RuntimePlatform.WindowsPlayer:
                    StandaloneCopyAsset();
                    break;
            }
        }
    }
    public override void End()
    {
        expectTime = timer;
        Debug.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer);
        if (!Application.isEditor)
        {
            switch (Application.platform)
            {
                case RuntimePlatform.Android:
                    AndroidProcessCopyComplete();
                    break;
                case RuntimePlatform.IPhonePlayer:
                    IOSProcessCopyComplete();
                    break;
            }
        }
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        timer += Time.deltaTime;
        if (!Application.isEditor)
        {
            switch (Application.platform)
            {
                case RuntimePlatform.Android:
                    AndroidWaitCopyAssetComplete();
                    break;
                case RuntimePlatform.IPhonePlayer:
                case RuntimePlatform.WindowsPlayer:
                    IOSorStandaloneWaitCopyAssetComplete();
                    break;
            }
        }
        ExceptionReport();
    }
    private void AndroidCopyAsset()
    {
        switch (VersionConfig.Get().assetAccess)
        {
            case InstalledAsset.FullAsset:
            case InstalledAsset.HalfAsset:
            case InstalledAsset.IngoreDownLoad:
                if (!SDKUtils.Instance.AssetCopyFinished)
                {
                    SDKUtils.Instance.CopyAsset();
                    done = false;
                    progress = 0f;
                }
                else
                {
                    done = true;
                }
                break;
            case InstalledAsset.NullAsset:
                done = true;
                break;
        }
    }
    private void IOSCopyAsset()
    {
        if (VersionUtility.Instance.versionInfo != null && VersionUtility.Instance.versionInfo.downAsset == 1)
        {
            switch (VersionConfig.Get().assetAccess)
            {
                case InstalledAsset.FullAsset:
                case InstalledAsset.HalfAsset:
                case InstalledAsset.IngoreDownLoad:
                    if (!SDKUtils.Instance.AssetCopyFinished)
                    {
                        copyTasks = new List<FileInfo>();
                        FileExtersion.GetAllDirectoryFileInfos(ResourcesPath.Instance.StreamingAssetPath, copyTasks);
                        for (var i = copyTasks.Count - 1; i >= 0; i--)
                        {
                            var fileInfo = copyTasks[i];
                            var destPath = fileInfo.FullName.Replace(ResourcesPath.Instance.StreamingAssetPath, ResourcesPath.Instance.ExternalStorePath);
                            if (File.Exists(destPath))
                            {
                                copyTasks.RemoveAt(i);
                            }
                        }
                        completedCount = 0;
                        totalCount = copyTasks.Count;
                    }
                    if (totalCount > 0)
                    {
                        done = false;
                        progress = 0f;
                    }
                    else
                    {
                        done = true;
                    }
                    break;
                case InstalledAsset.NullAsset:
                    done = true;
                    break;
            }
        }
        else
        {
            done = true;
        }
    }
    private void StandaloneCopyAsset()
    {
        if (VersionUtility.Instance.versionInfo != null && VersionUtility.Instance.versionInfo.downAsset == 1)
        {
            switch (VersionConfig.Get().assetAccess)
            {
                case InstalledAsset.FullAsset:
                case InstalledAsset.HalfAsset:
                case InstalledAsset.IngoreDownLoad:
                    copyTasks = new List<FileInfo>();
                    FileExtersion.GetAllDirectoryFileInfos(ResourcesPath.Instance.StreamingAssetPath, copyTasks);
                    for (var i = copyTasks.Count - 1; i >= 0; i--)
                    {
                        var fileInfo = copyTasks[i];
                        var destPath = fileInfo.FullName.Replace(ResourcesPath.Instance.StreamingAssetPath, ResourcesPath.Instance.ExternalStorePath);
                        if (File.Exists(destPath))
                        {
                            copyTasks.RemoveAt(i);
                        }
                    }
                    completedCount = 0;
                    totalCount = copyTasks.Count;
                    if (totalCount > 0)
                    {
                        done = false;
                        progress = 0f;
                    }
                    else
                    {
                        done = true;
                    }
                    break;
                case InstalledAsset.NullAsset:
                    done = true;
                    break;
            }
        }
        else
        {
            done = true;
        }
    }
    private void AndroidWaitCopyAssetComplete()
    {
        if (!SDKUtils.Instance.AssetCopyFinished)
        {
            done = false;
            progress = timer / duration;
        }
        else
        {
            done = true;
        }
    }
    private void IOSorStandaloneWaitCopyAssetComplete()
    {
        if (totalCount > 0)
        {
            if (completedCount < totalCount)
            {
                var fileInfo = copyTasks[0];
                var destPath = fileInfo.FullName.Replace(ResourcesPath.Instance.StreamingAssetPath, ResourcesPath.Instance.ExternalStorePath);
                var destDirectoryName = Path.GetDirectoryName(destPath);
                if (!Directory.Exists(destDirectoryName))
                {
                    Directory.CreateDirectory(destDirectoryName);
                }
                Debug.LogFormat("拷贝文件:{0}", fileInfo.Name);
                File.Copy(fileInfo.FullName, destPath, true);
                copyTasks.RemoveAt(0);
                completedCount++;
                done = false;
                progress = (float)completedCount / totalCount;
            }
            else
            {
                done = true;
            }
        }
        else
        {
            done = true;
        }
    }
    private void AndroidProcessCopyComplete()
    {
    }
    private void IOSProcessCopyComplete()
    {
        LocalSave.SetString("AssetCopyCompleted_IOSorStandalone", VersionConfig.Get().version);
    }
}
Main/Core/GameEngine/Launch/AssetCopyTask.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 64943b900511811419130066733f1396
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/AssetDeCompressTask.cs
New file
@@ -0,0 +1,204 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Threading;
public class AssetDeCompressTask
{
    public static string assetDeCompressVersion
    {
        get
        {
            return LocalSave.GetString("AssetDeCompressVersion");
        }
        set
        {
            LocalSave.SetString("AssetDeCompressVersion", value);
        }
    }
    public static bool assetDeCompressCompleted
    {
        get
        {
            if (string.IsNullOrEmpty(assetDeCompressVersion))
            {
                return false;
            }
            else
            {
                return assetDeCompressVersion == VersionConfig.Get().version;
            }
        }
    }
    public static void Decompress(string path)
    {
        var files = new List<FileInfo>();
        FileExtersion.GetAllDirectoryFileInfos(path, files);
        foreach (var item in files)
        {
            var fullName = item.FullName;
            if (fullName.EndsWith(".7z"))
            {
                SevenZipUtility.DeCompress(fullName, Path.GetDirectoryName(fullName));
            }
        }
    }
    public static DecompressProgress DecompressAync(string path)
    {
        var progress = new DecompressProgress();
        var files = new List<FileInfo>();
        FileExtersion.GetAllDirectoryFileInfos(path, files);
        for (var i = files.Count - 1; i >= 0; i--)
        {
            var fullName = files[i].FullName;
            if (!fullName.EndsWith(".7z"))
            {
                files.RemoveAt(i);
            }
        }
        var total = files.Count;
        if (total == 0)
        {
            progress.progress = 1f;
            progress.done = true;
            return progress;
        }
        ThreadPool.QueueUserWorkItem((object a) =>
        {
            var index = 0;
            foreach (var item in files)
            {
                var fullName = item.FullName;
                if (fullName.EndsWith(".7z"))
                {
                    SevenZipUtility.DeCompress(fullName, Path.GetDirectoryName(fullName));
                    index++;
                    progress.progress = index / (float)total;
                }
            }
            progress.done = true;
        });
        return progress;
    }
    public static void Delete7zFiles(string path)
    {
        var files = new List<FileInfo>();
        FileExtersion.GetAllDirectoryFileInfos(path, files);
        for (var i = files.Count - 1; i >= 0; i--)
        {
            var fullName = files[i].FullName;
            if (fullName.EndsWith(".7z"))
            {
                files[i].Delete();
            }
        }
    }
    public class DecompressProgress
    {
        object progressLock = new object();
        float m_Progress = 0f;
        public float progress
        {
            get
            {
                return m_Progress;
            }
            set
            {
                lock (progressLock)
                {
                    m_Progress = value;
                }
            }
        }
        object doneLock = new object();
        bool m_Done = false;
        public bool done
        {
            get
            {
                return m_Done;
            }
            set
            {
                lock (doneLock)
                {
                    m_Done = value;
                }
            }
        }
    }
}
public class AssetDecompressTask : LaunchTask
{
    public override float expectTime
    {
        get { return LocalSave.GetFloat("AssetDecompressTask_ExpectTime", 5f); }
        protected set { LocalSave.SetFloat("AssetDecompressTask_ExpectTime", value); }
    }
    AssetDeCompressTask.DecompressProgress deCompressProgress = null;
    float waitTimer = 0f;
    public override void Begin()
    {
        LaunchInHot.m_CurrentStage = LaunchStage.AssetDecompress;
        duration = Mathf.Max(0.5f, expectTime);
        if (!AssetDeCompressTask.assetDeCompressCompleted)
        {
            deCompressProgress = AssetDeCompressTask.DecompressAync(ResourcesPath.Instance.ExternalStorePath);
            done = false;
        }
        else
        {
            done = true;
        }
    }
    public override void End()
    {
        AssetDeCompressTask.assetDeCompressVersion = VersionConfig.Get().version;
        AssetDeCompressTask.Delete7zFiles(ResourcesPath.Instance.ExternalStorePath);
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        timer += Time.deltaTime;
        progress = timer / duration;
        if (deCompressProgress == null || deCompressProgress.done)
        {
            waitTimer += Time.deltaTime;
            if (waitTimer > 2f)
            {
                done = true;
            }
        }
    }
}
Main/Core/GameEngine/Launch/AssetDeCompressTask.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7ff0a94221f3cda4689ea3b7882f2562
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/BuiltInAssetCopyTask.cs
New file
@@ -0,0 +1,249 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
public class BuiltInAssetCopyTask : LaunchTask
{
    bool firstLaunch = false;
    public override void Begin()
    {
        duration = Mathf.Max(0.2f, expectTime);  //非安卓平台的时间,安卓由sdk拷贝完成回调
        if (Application.isEditor)
        {
            EditorCopyAsset();
        }
        else
        {
            //安卓每次由sdk回调拷贝成功,其他平台由unity自己存储标记
            switch (Application.platform)
            {
                case RuntimePlatform.Android:
                    AndroidCopyAsset();
                    break;
                case RuntimePlatform.IPhonePlayer:
                    IosCopyAsset();
                    break;
                case RuntimePlatform.WindowsPlayer:
                    StandaloneCopyAsset();
                    break;
            }
        }
        if (!firstLaunch)
        {
            done = true;
        }
    }
    public override void End()
    {
        if (!AssetSource.builtInFromEditor)
        {
            AssetBundleUtility.Instance.InitBuiltInAsset();
        }
        // TODO YYL
        // ConfigInitiator.SyncInit();
        // WindowCenter.Instance.DestoryWinsByStage(WindowCenter.WindowStage.Launch);
        // WindowCenter.Instance.OpenFromLocal<LaunchWin>();
        Language.InitDefaultLanguage();
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        if (!Application.isEditor)
        {
            //安卓每次由sdk回调拷贝成功,其他平台由unity自己存储标记
            if (Application.platform == RuntimePlatform.Android)
            {
                AndroidWaitCopyAssetComplete();
            }
            else
            {
                if (timer > duration)
                {
                    done = true;
                }
                else
                {
                    done = false;
                    progress = timer / duration;
                }
            }
        }
        timer += Time.deltaTime;
    }
    private void AndroidWaitCopyAssetComplete()
    {
        if (!SDKUtils.Instance.AssetCopyFinished)
        {
            done = false;
            progress = timer / duration;
        }
        else
        {
            done = true;
        }
    }
    private void AndroidCopyAsset()
    {
        if (!SDKUtils.Instance.AssetCopyFinished)
        {
            //每次由sdk回调拷贝成功
            firstLaunch = true;
            UnityEngine.Debug.Log("开始拷贝builtin资源");
            SDKUtils.Instance.CopyAsset(1);
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin_assetbundle");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin_assetbundle.manifest");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/musics");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/musics.manifest");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/prefabs");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/prefabs.manifest");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/sprites");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/sprites.manifest");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/animationclips");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/animationclips.manifest");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/materials");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/materials.manifest");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/scriptableobjects");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/scriptableobjects.manifest");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/font");
            //ynmbxxjUtil.Instance.CopyOneAsset("builtin/font.manifest");
            //foreach (var config in ConfigInitiator.builtinConfig)
            //{
            //    ynmbxxjUtil.Instance.CopyOneAsset("config/" + config);
            //}
            //AssetDeCompressTask.Decompress(ResourcesPath.Instance.ExternalStorePath);
            //LocalSave.SetString("BuiltInAssetCopyCompleted_Android", VersionConfig.Get().version);
        }
        else
            UnityEngine.Debug.Log("builtin资源已经拷贝过了");
    }
    private void IosCopyAsset()
    {
        if (!VersionUtility.Instance.InIosAuditTime())
        {
            if (!SDKUtils.builtinAssetCopyFinished)
            {
                firstLaunch = true;
                var targetDirectory = ResourcesPath.Instance.ExternalStorePath;
                if (!Directory.Exists(targetDirectory))
                {
                    Directory.CreateDirectory(targetDirectory);
                }
                var fileNames = new List<string>();
                //var files = new List<FileInfo>();
                //FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, "builtin"), files);
                //foreach (var file in files)
                //{
                //    var name = Path.GetFileName(file.FullName);
                //    fileNames.Add(StringUtility.Contact("builtin", Path.DirectorySeparatorChar, name));
                //}
                //fileNames.Add("builtin_assetbundle");
                //fileNames.Add("builtin_assetbundle.manifest");
                var configFiles = new List<FileInfo>();
                FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, "config"), configFiles);
                foreach (var file in configFiles)
                {
                    var name = Path.GetFileName(file.FullName);
                    fileNames.Add(StringUtility.Contact("config", Path.DirectorySeparatorChar, name));
                }
                foreach (var item in fileNames)
                {
                    var fromPath = StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, item);
                    var toPath = StringUtility.Contact(targetDirectory, item);
                    var destDirectoryName = Path.GetDirectoryName(toPath);
                    if (!Directory.Exists(destDirectoryName))
                    {
                        Directory.CreateDirectory(destDirectoryName);
                    }
                    File.Copy(fromPath, toPath, true);
                }
                LocalSave.SetString("BuiltInAssetCopyCompleted_IOSorStandalone", VersionConfig.Get().version);
            }
        }
    }
    private void StandaloneCopyAsset()
    {
        var targetDirectory = ResourcesPath.Instance.ExternalStorePath;
        if (!Directory.Exists(targetDirectory))
        {
            Directory.CreateDirectory(targetDirectory);
        }
        var fileNames = new List<string>();
        //var files = new List<FileInfo>();
        //FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, "builtin"), files);
        //foreach (var file in files)
        //{
        //    var name = Path.GetFileName(file.FullName);
        //    fileNames.Add(StringUtility.Contact("builtin", Path.DirectorySeparatorChar, name));
        //}
        //fileNames.Add("builtin_assetbundle");
        //fileNames.Add("builtin_assetbundle.manifest");
        var configFiles = new List<FileInfo>();
        FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, "config"), configFiles);
        foreach (var file in configFiles)
        {
            var name = Path.GetFileName(file.FullName);
            fileNames.Add(StringUtility.Contact("config", Path.DirectorySeparatorChar, name));
        }
        foreach (var item in fileNames)
        {
            var fromPath = StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, item);
            var toPath = StringUtility.Contact(targetDirectory, item);
            if (File.Exists(toPath))
            {
                continue;
            }
            var destDirectoryName = Path.GetDirectoryName(toPath);
            if (!Directory.Exists(destDirectoryName))
            {
                Directory.CreateDirectory(destDirectoryName);
            }
            File.Copy(fromPath, toPath, true);
        }
    }
    private void EditorCopyAsset()
    {
        if (!AssetSource.allFromEditor)
        {
            // FileExtersion.DirectoryCopy(ResourcesPath.CONFIG_FODLER, ResourcesPath.Instance.StreamingAssetPath + "config");
            // FileExtersion.DirectoryCopy(ResourcesPath.ResourcesOutPath + "BuiltIn", ResourcesPath.Instance.StreamingAssetPath + "builtin");
        }
    }
}
Main/Core/GameEngine/Launch/BuiltInAssetCopyTask.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1761a3254ef37ba4fbd60b602c1c786d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/CheckAssetValidTask.cs
New file
@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class CheckAssetValidTask : LaunchTask
{
    public override float expectTime
    {
        get { return LocalSave.GetFloat("CheckAssetValidTask_ExpectTime", 3f); }
        protected set { LocalSave.SetFloat("CheckAssetValidTask_ExpectTime", value); }
    }
    public override void Begin()
    {
        LaunchInHot.m_CurrentStage = LaunchStage.CheckAsset;
        duration = Mathf.Max(0.5f, expectTime);
        ServerListCenter.Instance.RequestJumpUrl();
        // TODO YYL
        // OperationLogCollect.Instance.RecordLauchEvent(2);
        // OperationLogCollect.Instance.RecordEvent(2);
        if (VersionUtility.Instance.NeedDownAsset())
        {
            var remoteURL = StringUtility.Contact(VersionUtility.Instance.versionInfo.GetResourcesURL(VersionConfig.Get().branch), Language.fixPath, "/config/PriorBundle.txt");
            var localURL = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, "config/PriorBundle.txt");
            var downloadTask = new DownloadTask(remoteURL, localURL);
            downloadTask.BeginDownload(AssetVersionUtility.OnDownLoadPriorBundle);
            //AssetVersionUtility.GetAssetVersionFile();
            done = false;
            progress = 0f;
        }
        else
        {
            //if (Application.isEditor)
            //    PatchLoader.InitLocalPatchAsset();
            done = true;
        }
    }
    public override void End()
    {
        expectTime = timer;
        Debug.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer);
        //  TODO YYL
        // GameNotice.OpenGameNotice();
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        timer += Time.deltaTime;
        if (!AssetVersionUtility.checkAssetCompleted)
        {
            done = false;
            progress = timer / expectTime;
        }
        else
        {
            done = true;
        }
        ExceptionReport();
    }
}
Main/Core/GameEngine/Launch/CheckAssetValidTask.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8a5baa7ec7f114141b60eae7f1ed95b6
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/DownLoadAssetTask.cs
New file
@@ -0,0 +1,277 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class DownLoadAssetTask : LaunchTask
{
    public override float expectTime
    {
        get { return LocalSave.GetFloat("DownLoadAssetTask_ExpectTime", 3f); }
        protected set { LocalSave.SetFloat("DownLoadAssetTask_ExpectTime", value); }
    }
    public override void Begin()
    {
        LaunchInHot.m_CurrentStage = LaunchStage.DownLoad;
        outTime = 9999f;
        duration = Mathf.Max(0.5f, expectTime);
        if (VersionUtility.Instance.NeedDownAsset())
        {
            if (!AssetVersionUtility.priorAssetDownLoadDone)
            {
                AssetVersionUtility.BeginDownLoadTask(true);
                done = false;
                progress = 0f;
            }
            else
            {
                done = true;
            }
        }
        else
        {
            done = true;
        }
    }
    public override void End()
    {
        expectTime = timer;
        Debug.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer);
        if (!AssetVersionUtility.unPriorAssetDownLoadDone)
        {
            AssetVersionUtility.BeginDownLoadTask(false);
        }
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        timer += Time.deltaTime;
        if (!AssetVersionUtility.priorAssetDownLoadDone)
        {
            done = false;
            progress = 0f;
        }
        else
        {
            done = true;
        }
        ExceptionReport();
    }
}
public class AssetBundleInitTask : LaunchTask
{
    public override float expectTime
    {
        get { return LocalSave.GetFloat("AssetBundleInitTask_ExpectTime", 1f); }
        protected set { LocalSave.SetFloat("AssetBundleInitTask_ExpectTime", value); }
    }
    public override void Begin()
    {
        LaunchInHot.m_CurrentStage = LaunchStage.AssetBundleInit;
        duration = Mathf.Max(0.5f, expectTime);
        if (!AssetSource.allFromEditor)
        {
            AssetBundleUtility.Instance.Initialize();
            done = false;
            progress = 0f;
        }
        else
        {
            done = true;
        }
    }
    public override void End()
    {
        expectTime = timer;
        //  TODO YYL
        // UILoader.LoadWindowAsync("LaunchBackGroundWin", null);
        Debug.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer);
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        if (AssetBundleUtility.Instance.initialized && AssetBundleUtility.Instance.initializedUIAssetBundle)
        {
            done = true;
        }
        else
        {
            done = false;
            progress = timer / duration;
        }
        ExceptionReport();
    }
}
public class ConfigInitTask : LaunchTask
{
    public override float expectTime
    {
        get { return LocalSave.GetFloat("ConfigInitTask_ExpectTime", 10f); }
        protected set { LocalSave.SetFloat("ConfigInitTask_ExpectTime", value); }
    }
    float threshold = 1f;
    public override void Begin()
    {
        LaunchInHot.m_CurrentStage = LaunchStage.ConfigInit;
        duration = Mathf.Max(0.5f, expectTime);
        threshold = Application.platform == RuntimePlatform.WindowsEditor ? 1f : 0.9f;
        // LaunchPostProcess.Instance.Begin();
        // InitialFunctionConfig.Init(true);   //有更新再初始化一次
    }
    public override void End()
    {
        expectTime = timer;
        Debug.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer);
        // TODO YYL
        // OperationLogCollect.Instance.RecordLauchEvent(3);
        // OperationLogCollect.Instance.RecordEvent(3);
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        timer += Time.deltaTime;
        // if (!ConfigInitiator.IsLoginConfigInited)\
        // TODO YYL
        // if (!ConfigInitiator.done)
        // {
        //     done = false;
        //     progress = timer / duration;
        // }
        // else
        {
            done = true;
        }
        ExceptionReport();
    }
}
public class LaunchFadeOutTask : LaunchTask
{
    public override float expectTime
    {
        get { return LocalSave.GetFloat("LaunchFadeOutTask_ExpectTime", 1f); }
        protected set { LocalSave.SetFloat("LaunchFadeOutTask_ExpectTime", value); }
    }
    public override void Begin()
    {
        LaunchInHot.m_CurrentStage = LaunchStage.Complete;
        duration = 0.5f;
        ShaderUtility.WarmUpAll();
        //SpeechTranslate.Instance.RequestGetToken();
        //  TODO CYL
        // WindowCenter.Instance.Open<LaunchBackGroundWin>(true);
        // var launchWin = WindowCenter.Instance.Get<LaunchWin>();
        // if (launchWin != null)
        // {
        //     launchWin.FadeOut();
        // }
        // try
        // {
        //     LogicLauncher.LaunchStart();
        // }
        // catch (Exception e)
        // {
        //     UnityEngine.Debug.LogError(e);
        // }
    }
    public override void End()
    {
        expectTime = timer;
        Debug.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer);
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        timer += Time.deltaTime;
        if (timer >= 0.5f)//&& ILLauncherProxy.Instance.started)
        {
            done = true;
        }
        else
        {
            done = false;
            progress = Mathf.Clamp01(timer / expectTime);
        }
        ExceptionReport();
    }
}
public class WaitTask : LaunchTask
{
    public WaitTask(float seconds)
    {
        expectTime = Mathf.Max(0.1f, seconds);
    }
    public override void Begin()
    {
    }
    public override void End()
    {
    }
    public override void Update()
    {
        timer += Time.deltaTime;
        if (timer >= expectTime)
        {
            done = true;
        }
        else
        {
            done = false;
            progress = Mathf.Clamp01(timer / expectTime);
        }
    }
}
Main/Core/GameEngine/Launch/DownLoadAssetTask.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 16185d13cc99c3443bb2e65696e1f1ce
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/GetVersionInfoTask.cs
New file
@@ -0,0 +1,78 @@
using UnityEngine;
using System.Collections;
using vnxbqy.UI;
using System;
using System.Collections.Generic;
using System.IO;
public class GetVersionInfoTask : LaunchTask
{
    public override float expectTime
    {
        get { return LocalSave.GetFloat("GetVersionInfoTask_ExpectTime", 1f); }
        protected set { LocalSave.SetFloat("GetVersionInfoTask_ExpectTime", value); }
    }
    public override void Begin()
    {
        LaunchInHot.m_CurrentStage = LaunchStage.ClientVersion;
        duration = Mathf.Max(0.5f, expectTime);
        if (Application.isEditor)
        {
            if (InGameDownTestUtility.enable)
            {
                VersionUtility.Instance.RequestVersionCheck();
                done = false;
                progress = 0f;
            }
            else
            {
                done = true;
            }
        }
        else
        {
            if (!VersionUtility.Instance.InIosAuditTime())
            {
                VersionUtility.Instance.RequestVersionCheck();
                done = false;
                progress = 0f;
            }
            else
            {
                done = true;
            }
        }
    }
    public override void End()
    {
        expectTime = timer;
        Debug.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer);
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        timer += Time.deltaTime;
        if (!VersionUtility.Instance.completed)
        {
            done = false;
            progress = timer / expectTime;
        }
        else
        {
            done = true;
        }
        ExceptionReport();
    }
}
Main/Core/GameEngine/Launch/GetVersionInfoTask.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e97b6f5762db50844882605678e5798d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/InitSettingTask.cs
New file
@@ -0,0 +1,54 @@
using UnityEngine;
public class InitSettingTask : LaunchTask
{
    public override float expectTime
    {
        get { return LocalSave.GetFloat("InitSettingTask_ExpectTime", 1f); }
        protected set { LocalSave.SetFloat("InitSettingTask_ExpectTime", value); }
    }
    public override void Begin()
    {
        ShaderUtility.InitGlobalParams();
        SoundPlayer.CreateSoundPlayer();
        SoundPlayer.Instance.PlayLoginMusic();
        SystemSetting.Instance.SetSoundVolume(SystemSetting.Instance.GetSoundVolume());
        SystemSetting.Instance.SetSoundEffect(SystemSetting.Instance.GetSoundEffect());
        SystemSetting.Instance.SetGameFps(SystemSetting.Instance.GetGameFps());
        SystemSetting.Instance.LetFPSUnLimit();
        DebugUtility.Instance.Init();
        DebugUtility.Instance.CreateDebugRoot();
        GameObjectPoolManager.Instance.gameObject.name = "GameObjectPool";
        GameObjectPoolManager.Instance.Initialize();
        //ExceptionCatcher.Init();
        //ExceptionCatcher.Catch();
        GlobalTimeEvent.Instance.Begin();
        PackageRegedit.Init();
        Clock.Init();
        // TODO YYL
        // if (VersionConfig.Get().appId.Equals("test"))
        // {
        //     SnxxzGame.Instance.gameObject.AddComponent<PocoManager>();
        // }
        done = true;
    }
    public override void End()
    {
        expectTime = timer;
    }
    public override void Update()
    {
        timer += Time.deltaTime;
    }
}
Main/Core/GameEngine/Launch/InitSettingTask.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ff71585fde92d814d97586fe3c01aa6d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/LaunchInHot.cs
New file
@@ -0,0 +1,180 @@
using UnityEngine;
using System.Collections;
using vnxbqy.UI;
using System;
using System.Collections.Generic;
using System.IO;
public class LaunchInHot : MonoBehaviour
{
    static int step = 0;
    public static LaunchStage m_CurrentStage = LaunchStage.None;
    public static LaunchProgressInfo progressInfo { get; private set; }
    float timer = 0f;
    Queue<LaunchTask> tasks = new Queue<LaunchTask>();
    LaunchTask currentTask = null;
    bool launchComplete = false;
    float surplusProgress = 0f;
    float surplusTime = 0f;
    void Start()
    {
        System.Net.ServicePointManager.DefaultConnectionLimit = 100;//设置http最大连接数
        Application.backgroundLoadingPriority = ThreadPriority.High;
        Screen.sleepTimeout = SleepTimeout.NeverSleep;
        SDKUtils.Instance.Init();  //原sdk接口
        var builtInAssetCopyTask = new BuiltInAssetCopyTask();
        var requestPermissionStart = new RequestPermissionStart();
        var initSettingTask = new InitSettingTask();
        var sdkInitedTask = new SDKInitedTask();
        //var assetCopyTask = new AssetCopyTask();
        //var assetDecompressTask = new AssetDecompressTask();
        var getVersionInfoTask = new GetVersionInfoTask();
        var checkAssetValidTask = new CheckAssetValidTask();
        var downLoadAssetTask = new DownLoadAssetTask();
        var assetBundleInitTask = new AssetBundleInitTask();
        var configInitTask = new ConfigInitTask();
        var launchFadeOutTask = new LaunchFadeOutTask();
        tasks.Enqueue(builtInAssetCopyTask);
        tasks.Enqueue(requestPermissionStart);
        tasks.Enqueue(initSettingTask);
        if (!Application.isEditor)
        {
            tasks.Enqueue(sdkInitedTask);
        }
        switch (Application.platform)
        {
            case RuntimePlatform.OSXEditor:
            case RuntimePlatform.WindowsEditor:
                tasks.Enqueue(getVersionInfoTask);
                break;
            case RuntimePlatform.Android:
                tasks.Enqueue(getVersionInfoTask);
                //tasks.Enqueue(assetCopyTask);
                //tasks.Enqueue(assetDecompressTask);
                break;
            case RuntimePlatform.IPhonePlayer:
                tasks.Enqueue(getVersionInfoTask);
                //tasks.Enqueue(assetCopyTask);
                break;
            case RuntimePlatform.WindowsPlayer:
                //tasks.Enqueue(assetCopyTask);
                tasks.Enqueue(getVersionInfoTask);
                break;
        }
        tasks.Enqueue(checkAssetValidTask);
        tasks.Enqueue(downLoadAssetTask);
        tasks.Enqueue(assetBundleInitTask);
        tasks.Enqueue(configInitTask);
        tasks.Enqueue(launchFadeOutTask);
        CalculateExpectTotalTime();
    }
    void Update()
    {
        if (!launchComplete)
        {
            if (currentTask == null)
            {
                if (tasks.Count > 0)
                {
                    currentTask = tasks.Dequeue();
                    currentTask.Begin();
                }
                else
                {
                    launchComplete = true;
                }
            }
            if (currentTask != null)
            {
                currentTask.Update();
            }
            if (currentTask != null && currentTask.done)
            {
                currentTask.End();
                CalculateExpectTotalTime();
                currentTask = null;
            }
            if (m_CurrentStage == LaunchStage.DownLoad)
            {
                progressInfo = new LaunchProgressInfo(m_CurrentStage, 1, progressInfo.totalProgress, 0f);
            }
            else
            {
                timer += Time.deltaTime;
                var progress = progressInfo.totalProgress + surplusProgress * (Time.deltaTime / surplusTime);
                progress = Mathf.Clamp(progress, 0, 0.98f);
                var partProgress = 0f;
                if (currentTask == null)
                {
                    partProgress = 0f;
                }
                else
                {
                    var temp = currentTask.timer / Mathf.Min(2f, currentTask.duration);
                    step = (int)temp + 1;
                    partProgress = temp - (int)temp;
                }
                progressInfo = new LaunchProgressInfo(m_CurrentStage, step, Mathf.Clamp01(progress), partProgress);
            }
        }
        if (launchComplete)
        {
            UnityEngine.Debug.LogFormat("启动耗时:{0}", timer);
            progressInfo = new LaunchProgressInfo(m_CurrentStage, 1, 1f, 1f);
            this.enabled = false;
            // 启动流程结束 要去哪里 TODO YYL
            // StageLoad.Instance.PushSceneLoadCommand(new StageLoad.StageLoadCommand()
            // {
            //     toMapId = 1,
            //     toLineId = 0,
            //     needEmpty = false,
            //     needLoadResource = true,
            //     serverType = ServerType.Main,
            //     isClientLoadMap = true
            // });
        }
    }
    public static int GetLaunchStage()
    {
        return (int)m_CurrentStage;
    }
    /// <summary>
    /// 计算总的预期时间
    /// </summary>
    void CalculateExpectTotalTime()
    {
        surplusTime = 0f;
        foreach (var item in tasks)
        {
            surplusTime += item.expectTime;
        }
        surplusProgress = 1 - progressInfo.totalProgress;
    }
}
Main/Core/GameEngine/Launch/LaunchInHot.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 906ac694e0545124cbf74afe1c69b703
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/LaunchProgressInfo.cs
New file
@@ -0,0 +1,17 @@
public struct LaunchProgressInfo
{
    public LaunchStage stage;
    public int step;
    public float totalProgress;
    public float partProgress;
    public LaunchProgressInfo(LaunchStage stage, int step, float totalProgress, float partProgress)
    {
        this.stage = stage;
        this.step = step;
        this.totalProgress = totalProgress;
        this.partProgress = partProgress;
    }
}
Main/Core/GameEngine/Launch/LaunchProgressInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4ab1175bb98c09842bf2bb1026a8d7cb
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/LaunchStage.cs
New file
@@ -0,0 +1,14 @@
public enum LaunchStage
{
    None = 0,
    SDKInit = 1,
    AssetCopy = 2,
    AssetDecompress = 3,
    ClientVersion = 4,
    CheckAsset = 5,
    DownLoad = 6,
    AssetBundleInit = 7,
    ConfigInit = 8,
    Complete = 9,
}
Main/Core/GameEngine/Launch/LaunchStage.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f3341cae2e8b8e64fba6fedb5d37723a
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/LaunchTask.cs
New file
@@ -0,0 +1,34 @@
using UnityEngine;
public abstract class LaunchTask
{
    public float timer { get; protected set; }
    public float duration { get; protected set; }
    bool exceptionReported = false;
    public bool done { get; protected set; }
    public float progress { get; protected set; }
    public virtual float expectTime { get; protected set; }
    protected float outTime = 15f;
    public abstract void Begin();
    public abstract void Update();
    public abstract void End();
    public void ExceptionReport()
    {
        if (!exceptionReported && timer > outTime && !done)
        {
            var content = string.Format("任务:{0};网络状态:{1}", this.GetType().Name, Application.internetReachability);
            exceptionReported = true;
        }
    }
}
Main/Core/GameEngine/Launch/LaunchTask.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8f8006ef67733114da2ae2e8e0679323
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/RequestPermissionStart.cs
New file
@@ -0,0 +1,38 @@
//同意隐私权限后才可以申请权限
public class RequestPermissionStart : LaunchTask
{
    public override void Begin()
    {
        if (LocalSave.GetBool("secretToggleStart5"))
        {
            SDKUtils.Instance.IsAgreeSecret = true;
            SDKUtils.Instance.RequestAndroidPermissionStart();
        }
        else
        {
            //先弹隐私政策,同意之后才可以申请权限 继续游戏
            // YYL TODO
            // WindowCenter.Instance.OpenFromLocal<RequestSecretWin>();
        }
    }
    public override void End()
    {
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        if  (SDKUtils.Instance.IsAgreeSecret)
        {
            done = true;
        }
    }
}
Main/Core/GameEngine/Launch/RequestPermissionStart.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d683f8dc80b4bf24b93f9be3077bd724
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Launch/SDKInitedTask.cs
New file
@@ -0,0 +1,58 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
public class SDKInitedTask : LaunchTask
{
    public override float expectTime
    {
        get { return LocalSave.GetFloat("SDKInitedTask_ExpectTime", 1f); }
        protected set { LocalSave.SetFloat("SDKInitedTask_ExpectTime", value); }
    }
    public override void Begin()
    {
        LaunchInHot.m_CurrentStage = LaunchStage.SDKInit;
        duration = Mathf.Max(0.1f, expectTime);
    }
    public override void End()
    {
        expectTime = timer;
        Debug.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer);
        // TODO YYL
        // OperationLogCollect.Instance.RecordLauchEvent(1);
        // OperationLogCollect.Instance.RecordEvent(1);
        var cpu = 2;
        var memory = 2048;
        DeviceUtility.GetCpuAndMemory(out cpu, out memory);
        Debug.LogFormat("获得机器信息:cpu {0}----内存 {1}", cpu, memory);
    }
    public override void Update()
    {
        if (done)
        {
            return;
        }
        timer += Time.deltaTime;
        if (SDKUtils.Instance.InitFinished)
        {
            done = true;
        }
        else
        {
            done = false;
            progress = timer / duration;
        }
        ExceptionReport();
    }
}
Main/Core/GameEngine/Launch/SDKInitedTask.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6bf40baa355319f45b1de7b03576713a
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/GameEngine/Login.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8eda8f1b1cda90b408dd25bd730b25ab
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Manager/ResManager.cs
@@ -128,7 +128,16 @@
        
    }
    public string GetAssetFilePath(string _assetKey)
    {
        var path = Path.Combine(ExternalStorePath, _assetKey);
        if (!File.Exists(path))
        {
            path = Path.Combine(StreamingAssetPath, _assetKey);
        }
        return path;
    }
}
Main/Manager/StageManager.cs
@@ -13,9 +13,9 @@
{
    public StageName currentStage;
    public Action AfterEnterGame;
    public Action AfterLoadingGameScene;
    public Action BeforeEnterGame;
    public Action BeforeLoadingGameScene;
    // public Action OnSwitchAccount;
@@ -26,8 +26,8 @@
    public void Release()
    {
        AfterEnterGame = null;
        BeforeEnterGame = null;
        AfterLoadingGameScene = null;
        BeforeLoadingGameScene = null;
    }
    public async UniTaskVoid ToLoginScene()
@@ -70,8 +70,8 @@
    public async UniTaskVoid ToGameScene()
    {
        UIManager.Instance.DestroyAllUI();
        AfterEnterGame?.Invoke();
        BeforeLoadingGameScene?.Invoke();
        // ResManager.Instance.PrewarmResources();
@@ -82,7 +82,7 @@
        //  加载初始化数据完成
        currentStage = StageName.Game;
        BeforeEnterGame?.Invoke();
        AfterLoadingGameScene?.Invoke();
        UIManager.Instance.OpenWindow<MainWin>();
    }
Main/ResModule/AssetBundle/AssetBundleUtility.cs
@@ -3,7 +3,7 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
public class AssetBundleUtility : SingletonMonobehaviour<AssetBundleUtility>
{
@@ -97,23 +97,23 @@
        assetBundle = null;
    }
    public IEnumerator Initialize()
    public async UniTask Initialize()
    {
        yield return StartCoroutine(Co_LoadMainfestFile("audio"));
        yield return StartCoroutine(Co_LoadMainfestFile("video"));
        yield return StartCoroutine(Co_LoadMainfestFile("mobeffectshader"));
        yield return StartCoroutine(Co_LoadMainfestFile("config"));
        yield return StartCoroutine(Co_LoadMainfestFile("maps"));
        yield return StartCoroutine(Co_LoadMainfestFile("ui"));
        await Co_LoadMainfestFile("audio");
        await Co_LoadMainfestFile("video");
        await Co_LoadMainfestFile("mobeffectshader");
        await Co_LoadMainfestFile("config");
        await Co_LoadMainfestFile("maps");
        await Co_LoadMainfestFile("ui");
        yield return StartCoroutine(Co_LoadAssetBundle(ResourcesPath.windowFileBundleName));
        yield return StartCoroutine(Co_LoadAssetBundle(ResourcesPath.uiprefabFileBundleName));
        await Co_LoadAssetBundle(ResourcesPath.windowFileBundleName);
        await Co_LoadAssetBundle(ResourcesPath.uiprefabFileBundleName);
        initializedUIAssetBundle = true;
        initialized = true;
    }
    private IEnumerator Co_LoadMainfestFile(string _category)
    private async UniTask Co_LoadMainfestFile(string _category)
    {
        var path = AssetVersionUtility.GetAssetFilePath(StringUtility.Contact(AssetVersionUtility.EncodeFileName(_category), "_assetbundle"), false);
        var _assetBundle = AssetBundle.LoadFromFile(path);
@@ -121,14 +121,14 @@
        if (_assetBundle == null)
        {
            Debug.LogErrorFormat("AssetBundleManifest的包文件为空或者加载出错.  Path:{0}", path);
            yield break;
            return;
        }
        AssetBundleManifest _assetBundleManifest = _assetBundle.LoadAsset<AssetBundleManifest>(ResourcesPath.AssetDependentFileAssetName);
        if (_assetBundleManifest == null)
        {
            Debug.LogErrorFormat("AssetBundleManifest的包文件为空或者加载出错.  Path:{0}", path);
            yield break;
            return;
        }
        string[] _assetBundleNames = _assetBundleManifest.GetAllAssetBundles();
@@ -172,10 +172,10 @@
            return;
        }
        StartCoroutine(Co_DoLoadAsset(assetBundleName, assetName, callBack));
        Co_DoLoadAsset(assetBundleName, assetName, callBack).Forget();
    }
    private IEnumerator Co_LoadAssetBundle(string assetBundleName)
    private async UniTask<AssetBundle> Co_LoadAssetBundle(string assetBundleName)
    {
#if UNITY_5||UNITY_5_3_OR_NEWER
        assetBundleName = assetBundleName.ToLower();
@@ -183,7 +183,7 @@
        if (JudgeExistAssetBundle(assetBundleName))
        {
            yield break;
            return m_AssetBundleDict[assetBundleName];
        }
        if (m_LoadingAssetBundleList.Contains(assetBundleName))
@@ -191,9 +191,9 @@
            while (!m_AssetBundleDict.ContainsKey(assetBundleName))
            {
                // Debug.Log(Time.frameCount + " ] 正在加载AssetBundle: " + assetBundleName + ", 请等待...");
                yield return null;
                await UniTask.Yield();
            }
            yield break;
            return m_AssetBundleDict[assetBundleName];
        }
        m_LoadingAssetBundleList.Add(assetBundleName);
@@ -202,12 +202,13 @@
        if (_assetBundleInfo == null)
        {
            Debug.LogErrorFormat("Co_LoadAssetBundle(): {0}出现错误 => 不存在AssetBundleInfo. ", assetBundleName);
            yield break;
            m_LoadingAssetBundleList.Remove(assetBundleName);
            return null;
        }
        if (_assetBundleInfo.dependentBundles.Length > 0)
        {
            yield return Co_LoadAssetBundleDependenice(_assetBundleInfo);
            await Co_LoadAssetBundleDependenice(_assetBundleInfo);
        }
        var isBuiltin = assetBundleName.Contains("builtin");
@@ -216,44 +217,41 @@
        Debug.LogFormat("Co_LoadAssetBundle(): 将要加载的assetBundle包路径 => {0}", filePath);
        var _request = AssetBundle.LoadFromFileAsync(filePath);
        while (!_request.isDone)
        {
            yield return null;
        }
        await _request;
        CacheAssetBundle(assetBundleName, _request.assetBundle);
        m_LoadingAssetBundleList.Remove(assetBundleName);
        return _request.assetBundle;
    }
    private IEnumerator Co_LoadAssetBundleDependenice(AssetBundleInfo assetBundleInfo)
    private async UniTask Co_LoadAssetBundleDependenice(AssetBundleInfo assetBundleInfo)
    {
        AssetBundle _assetBundle = null;
        if (assetBundleInfo.dependentBundles == null
         || assetBundleInfo.dependentBundles.Length == 0)
        {
            yield break;
            return;
        }
        for (int i = 0; i < assetBundleInfo.dependentBundles.Length; ++i)
        {
            if (m_AssetBundleDict.TryGetValue(assetBundleInfo.dependentBundles[i], out _assetBundle) == false)
            {
                yield return Co_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
                await Co_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
            }
            else
            {
                if (_assetBundle == null)
                {
                    yield return Co_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
                    await Co_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
                }
            }
        }
    }
    private IEnumerator Co_DoLoadAsset(string assetBundleName, string assetName, Action<bool, UnityEngine.Object> callBack = null)
    private async UniTask Co_DoLoadAsset(string assetBundleName, string assetName, Action<bool, UnityEngine.Object> callBack = null)
    {
#if UNITY_5||UNITY_5_3_OR_NEWER
        assetBundleName = assetBundleName.ToLower();
@@ -263,7 +261,7 @@
        RunTimeABLoadLog.AddLog(assetBundleName, assetName, UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);
#endif
        yield return Co_LoadAssetBundle(assetBundleName);
        await Co_LoadAssetBundle(assetBundleName);
        if (!m_AssetBundleDict.ContainsKey(assetBundleName))
        {
@@ -271,7 +269,7 @@
            {
                callBack(false, null);
            }
            yield break;
            return;
        }
        string _checkTag = assetBundleName + "@" + assetName;
@@ -281,7 +279,7 @@
                || !m_AssetDict[assetBundleName].ContainsKey(assetName))
            {
                //                Debug.Log(Time.frameCount + " ] 正在加载Asset: " + _checkTag + ", 请等待...");
                yield return null;
                await UniTask.Yield();
            }
            if (callBack != null)
@@ -289,16 +287,13 @@
                callBack(true, m_AssetDict[assetBundleName][assetName]);
            }
            yield break;
            return;
        }
        m_LoadingAssetList.Add(_checkTag);
        var request = m_AssetBundleDict[assetBundleName].LoadAssetAsync(assetName);
        while (!request.isDone)
        {
            yield return null;
        }
        await request;
        if (request.asset != null)
        {
@@ -319,14 +314,14 @@
        m_LoadingAssetList.Remove(_checkTag);
    }
    private IEnumerator Co_DoLoadAsset(AssetInfo assetInfo, Action<bool, UnityEngine.Object> callBack = null)
    private async UniTask Co_DoLoadAsset(AssetInfo assetInfo, Action<bool, UnityEngine.Object> callBack = null)
    {
        if (assetInfo == null)
        {
            Debug.LogErrorFormat("Co_DoLoadAsset(): {0}, 出现错误 => 存入的AssetInfo为null. ", assetInfo);
            yield break;
            return;
        }
        yield return Co_DoLoadAsset(assetInfo.assetBundleName, assetInfo.name, callBack);
        await Co_DoLoadAsset(assetInfo.assetBundleName, assetInfo.name, callBack);
    }
    #endregion
Main/Utility/SevenZipUtility.cs
New file
@@ -0,0 +1,45 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class SevenZipUtility
{
    static string m_SevenZipToolPath = string.Empty;
    static string sevenZipToolPath {
        get {
            if (string.IsNullOrEmpty(m_SevenZipToolPath))
            {
                if (Directory.Exists("C:/Program Files/7-Zip"))
                {
                    m_SevenZipToolPath = "C:/Program Files/7-Zip";
                }
                else
                {
                    m_SevenZipToolPath = "C:/Program Files (x86)/7-Zip";
                }
            }
            return m_SevenZipToolPath;
        }
    }
    public static void Compress(string from, string to)
    {
        if (File.Exists(to))
        {
            File.Delete(to);
        }
        var cmd = string.Format("\"{0}\\7z\" a {1} {2} -mx9", sevenZipToolPath, to, from);
        SystemCMD.RunCmd(cmd);
    }
    public static void DeCompress(string from, string to)
    {
#if !(UNITY_IOS || UNITY_IPHONE)
        lzma.doDecompress7zip(from, to, false, true);
#endif
    }
}
Main/Utility/SevenZipUtility.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b621d727b43cf804d96bdadc965bc774
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Utility/ShaderUtility.cs
New file
@@ -0,0 +1,28 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShaderUtility
{
    public static void InitGlobalParams()
    {
        Shader.SetGlobalColor("_Gbl_Lgt", new Color(0.8f, 0.8f, 0.8f, 1));
        Shader.SetGlobalColor("_Gbl_Pnt", new Color(1, 1, 1, 1));
        Shader.SetGlobalColor("_Gbl_Amb", new Color(1, 1, 1, 1));
        Shader.SetGlobalColor("_Gbl_Spc", new Color(0.8f, 0.8f, 0.8f, 1));
        Shader.SetGlobalColor("_Gbl_Rim", new Color(1, 1, 1, 1));
        Shader.SetGlobalColor("_Gbl_Wat", new Color(1, 1, 1, 1));
    }
    public static void WarmUpAll()
    {
        if (!AssetSource.shaderFromEditor)
        {
            AssetBundleUtility.Instance.Sync_LoadAllAssets("graphic/shader");
            Shader.WarmupAllShaders();
        }
    }
}
Main/Utility/ShaderUtility.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 474969e2043f6864aad54234f84d18c3
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant: