Пример #1
0
        public static string ToString <T>(T target)
        {
            Type type = typeof(T);

            if (type.IsGenericType)
            {
                if (type.GetGenericTypeDefinition() == typeof(List <>))
                {
                    object ret = ToListStringMethodInfo
                                 .MakeGenericMethod(type.GetGenericArguments())
                                 .Invoke(null, new object[] { target });
                    return(ret != null?ret.ToString() : null);
                }
                else if (type.GetGenericTypeDefinition() == typeof(Dictionary <,>))
                {
                    object ret = ToMapStringMethodInfo
                                 .MakeGenericMethod(type.GetGenericArguments())
                                 .Invoke(null, new object[] { target });
                    return(ret != null?ret.ToString() : null);
                }
                DebugUtils.Assert(false, "ToString Not Found Type: " + typeof(T).FullName);
                return(null);
            }
            else if (type.BaseType == typeof(Enum))
            {
                return(EnumUtils.EnumToString(target));
            }
            MethodInfo info = GetToStringMethod <T>();

            DebugUtils.Assert(info != null, "GetToStringMethod Not Found Type: " + typeof(T).FullName);
            GenericParametersObjectOne[0] = target;
            object result = info.Invoke(null, GenericParametersObjectOne);

            return(result != null?result.ToString() : null);
        }
Пример #2
0
        public override bool CompareTo(GenericValue param)
        {
            StateGenericValue <T> p = param as StateGenericValue <T>;

            DebugUtils.Assert(p != null, "");
            return(CompareTo(p.Value));
        }
Пример #3
0
        public float timePausePoint = -1; // 暂停时间戳

        /// <summary>
        /// 更新数据
        /// 如果没被暂停过,则UpdateTime只会执行一次
        /// 如果被暂停过,timePausePoint不会小于0
        /// </summary>
        /// <returns></returns>
        public bool UpdateTime()
        {
            // 表示已执行
            if (timeStartPoint > 0)
            {
                // 计算已执行时长
                float timeEllappsed = 0;
                if (bNature)
                {
                    // 自然时长处理
                    // 当前时长减去执行时长,得已执行时长
                    timeEllappsed = Time.realtimeSinceStartup - timeStartPoint;
                }
                else
                {
                    // 非自然时长,即暂停的时长不考虑
                    if (timePausePoint < 0)
                    {
                        timePausePoint = Time.realtimeSinceStartup;
                        // UpdateTime 被多次执行,说明被暂停过,不应该执行到这里
                        DebugUtils.Assert(false, "wrong");
                    }
                    // 暂停的时间点减去开启的时间点,得到实际执行时长
                    timeEllappsed = timePausePoint - timeStartPoint;
                }
                // 更新剩余时长
                timeValue = timeValue - timeEllappsed;
            }
            // 更新当前执行时间起点
            timeStartPoint = DateTimeUtils.GetTimeStampSeconds();
            return(timeValue > 0);
        }
Пример #4
0
 internal void Kill(ISequnceUpdate su)
 {
     DebugUtils.Assert(!IsLockUpdate(), "Kill");
     su.Kill();
     mBehaviours.Remove(su);
     mInactiveBehaviours.Remove(su);
 }
Пример #5
0
 /// <summary>
 /// 每帧都会执行
 /// </summary>
 /// <param name="timeLine">absolute time</param>
 /// <returns>执行结束,返回 false; 否之,返回 true</returns>
 internal bool Update(float timeLine)
 {
     if (mState == ThreeState.Finished)
     {
         return(false);
     }
     // 这里是绝对时长
     mTimeElappsed = timeLine;
     if (mTimeElappsed >= StartTime)
     {
         if (mState == ThreeState.Ready)
         {
             Begin();
         }
         if (IsEnd())
         {
             if (mState == ThreeState.Playing)
             {
                 End();
             }
         }
         else
         {
             DebugUtils.Assert(mState == ThreeState.Playing, "wrong");
             Process();
         }
     }
     return(mState != ThreeState.Finished);
 }
Пример #6
0
        public static Properties Create(string url)
        {
            if (string.IsNullOrEmpty(url))
            {
                DebugUtils.Assert(false, "Attempting to create a Properties object from an empty URL!");
                return(null);
            }
            // Calculate the file and full namespace path from the specified url.
            string        urlString     = url;
            string        fileString    = null;
            List <string> namespacePath = new List <string>();

            CalculateNamespacePath(ref urlString, ref fileString, namespacePath);
            if (File.Exists(fileString))
            {
                return(CreateFromContent(File.ReadAllText(fileString), url));
            }
            else
            {
                Properties p = new Properties();
                p.mNamespace = fileString;
                p.mId        = Path.GetFileNameWithoutExtension(fileString);
                p.SetDirectoryPath(fileString);
                return(p);
            }
        }
Пример #7
0
        /// <summary>
        /// 0. 加载:引用计数设计
        ///     0. 区分 主包加载 和 依赖包加载。LoadBundleAsync和LoadBundleSync均是主包加载
        ///     1. 主包加载:所有依赖的包(A,B,C,...) 引用只加1,不区分某些依赖包A还依赖了其他的依赖包(B...)
        ///     2. 之前主包加载时,某个依赖包A被加载,此时的计数为1
        ///     3. 现在 A 作为主包加载,A所有依赖的包 引用只加1。此时 A 计数为 2,A依赖的B也为2
        ///     4. 再次 A 作为主包加载,直接返回 A 包,不再做引用计数
        ///     5. 注意:依赖的层次不要深,最好都是小范围依赖。打包时,要做好规划。
        ///
        /// 1. 异步加载:回调设计
        ///     1. 参数: 主包 总依赖数量 和 已经加载依赖的数量
        ///     2. 依赖包未加载,依赖包加载的接口注册complete:完成时要让 主包 依赖加载数量剩余完成 -1
        ///     3. 依赖包已加载,直接 让主包 依赖加载数量剩余完成 -1
        ///     4. 主包已加载:上层接口直接回调,此时有可能依赖未加载完。Bundle内部检测是否执行回调
        ///     5. 主包完成数量等于总数量,则主包执行给上层的 加载完成 回调
        ///
        /// 2. 同步加载
        ///     1. 同步加载和异步加载区别在:CreateBundle
        ///     2. 如果之前存在异步加载,现在同步打断异步:rootBundle.Sync(SyncInterruptAsync);
        ///         1. 所有异步加载的依赖包需转同步
        ///
        /// 3. 只有同步打断异步,不存在异步打断同步
        ///
        /// </summary>
        /// <param name="rootBundleName">主包:ab包名</param>
        /// <param name="isAsync">是否异步</param>
        /// <returns></returns>
        protected Bundle LoadBundle(string rootBundleName, bool isAsync)
        {
            Bundle rootBundle = GetBundle(rootBundleName);

            // 目前不存在 或者 之前通过被依赖而加载
            if (rootBundle == null || IsDependence(rootBundle))
            {
                // 目前不存在
                if (rootBundle == null)
                {
                    // 创建 bundle
                    rootBundle = CreateBundle(rootBundleName, false, isAsync);
                }
                // 设置为主包,而非 依赖包
                SetIsDependence(rootBundleName, false);
                // 引用 + 1
                rootBundle.AddRef();
                // 获取所有依赖ab
                string[] bundles = GetAllDependencies(rootBundleName);
                // 设置依赖包剩余加载数
                rootBundle.LeftDependenceCount = bundles.Length;
                foreach (string dependenceBundleName in bundles)
                {
                    Bundle dependenceBundle = GetBundle(dependenceBundleName);
                    // 不存在
                    if (dependenceBundle == null)
                    {
                        // 加载 依赖
                        dependenceBundle = CreateBundle(dependenceBundleName, true, isAsync);
                        // 添加 依赖
                        rootBundle.AddDependece(dependenceBundle);
                    }
                    // 引用 + 1
                    dependenceBundle.AddRef();
                    // 依赖异步加载中
                    if (dependenceBundle.IsAsyncLoading)
                    {
                        AssetBundleCreateRequest req = GetAssetBundleCreateRequest(dependenceBundleName);
                        req.completed += (asyncOperation) =>
                        {
                            // 依赖已经加载好了, root 剩余数量-1
                            rootBundle.OneDependenceLoaded();
                        };
                    }
                    else
                    {
                        // 依赖已经加载好了, root 剩余数量-1
                        rootBundle.OneDependenceLoaded();
                    }
                }
            }
            DebugUtils.Assert(IsContain(rootBundleName) && !IsDependence(rootBundleName), string.Format("{0} wrong", rootBundleName));
            // 同步时,才检查是否存在异步加载的AB
            if (!isAsync)
            {
                rootBundle.Sync(SyncInterruptAsync);
            }
            return(rootBundle);
        }
Пример #8
0
        public static float Modf(float v, float div)
        {
            DebugUtils.Assert(v >= 0, "");
            DebugUtils.Assert(div > 0, "");
            int times = (int)(v / div);

            return(v - times * div);
        }
Пример #9
0
 protected internal virtual void SetStartDurationTime(float startTime, float duration)
 {
     DebugUtils.Assert(mState == ThreeState.Ready, "");
     mOriginStartTime = startTime;
     StartTime        = startTime;
     mDuration        = duration;
     // EndTime = StartTime + mDuration;
 }
Пример #10
0
        public bool CheckCondition(GenericValue condition)
        {
            DebugUtils.Assert(condition != null, "wrong condition");
            GenericValue param = mParameters[condition.Name];

            DebugUtils.Assert(param != null, "wrong parameter");
            return(condition.CompareTo(param));
        }
Пример #11
0
 public Buff this[int index]
 {
     get
     {
         DebugUtils.Assert(index < Count, "");
         return(mBuffs[index]);
     }
 }
Пример #12
0
 public string this[int row, int col]
 {
     get
     {
         DebugUtils.Assert(row < RowCount && col < ColCount, "");
         return(mDatas[row][col]);
     }
 }
Пример #13
0
        internal void Replay(ISequnceUpdate su)
        {
            DebugUtils.Assert(!IsLockUpdate(), "Kill");
            bool contains = mInactiveBehaviours.Remove(su);

            if (contains)
            {
                AddSequence(su);
            }
            su.Replay();
        }
Пример #14
0
        public T Acquire <T>() where T : ObjectBase
        {
            Type type = typeof(T);

            DebugUtils.Assert(type.GetConstructor(Type.EmptyTypes) != null, "no default constructor");
            if (!mPools.ContainsKey(type))
            {
                mPools.Add(type, new ObjectPool(type));
            }
            return(mPools[type].Acquire() as T);
        }
Пример #15
0
 public void Set <U>(string paraName, U value)
 {
     if (mParameters.ContainsKey(paraName))
     {
         StateGenericValue <U> param = mParameters[paraName] as StateGenericValue <U>;
         DebugUtils.Assert(param != null, "");
         if (!param.Value.Equals(value))
         {
             param.Value = value;
             Update(paraName);
         }
     }
 }
Пример #16
0
        // 考虑 relateDir = "/"
        // 末尾都不带 "/"
        // ("/", AssetbundleInfoFile, false)
        public static string GetFilePath(string relateDir, string fileName, bool isLocal)
        {
            DebugUtils.Assert(!string.IsNullOrEmpty(relateDir), "GetFilePath");
            string format = "{0}/{1}/{2}";

            if (relateDir == "/")
            {
                format = "{0}{1}{2}";
            }
            string baseDir = isLocal ? LocalAssetbundleDir : RemoteAssetbundleDir;

            return(string.Format(format, baseDir, relateDir, fileName));
        }
Пример #17
0
 public void Update(string paramName)
 {
     if (Current != null && Current.ContainParameter(paramName))
     {
         T    nextTransfer;
         bool isDirty = Current.CheckTransfer(out nextTransfer);
         if (isDirty)
         {
             DebugUtils.Assert(!nextTransfer.Equals(Current.StateType), "wrong changed state");
             ChangeStatus(nextTransfer);
         }
     }
 }
Пример #18
0
        public static Properties ConvertXMLToPropertiesFromContent(string content, string filePath)
        {
            if (string.IsNullOrEmpty(content))
            {
                DebugUtils.Assert(false, "Attempting to create a Properties object from an empty URL!");
                return(null);
            }
            SecurityParser securityParser = new SecurityParser();

            securityParser.LoadXml(content);
            SecurityElement xml = securityParser.ToXml();

            return(Properties.CreateFromXml(xml, filePath));
        }
Пример #19
0
 public void Clear()
 {
     DebugUtils.Assert(!IsLockUpdate(), "Clear");
     foreach (ISequnceUpdate su in  mBehaviours)
     {
         su.Kill();
     }
     mBehaviours.Clear();
     foreach (ISequnceUpdate su in mInactiveBehaviours)
     {
         su.Kill();
     }
     mInactiveBehaviours.Clear();
 }
Пример #20
0
        private static MethodInfo GetToObjectMethodInfoFromCache(Type type)
        {
            if (GenericMethodInfos.ContainsKey(type))
            {
                return(GenericMethodInfos[type]);
            }
            GenericParameterTypesOne[0] = type;
            MethodInfo keyMethod = GetToObjectMethodInfo.MakeGenericMethod(GenericParameterTypesOne);

            DebugUtils.Assert(keyMethod != null, "GetToObjectMethod Not Found Type1: " + type.FullName);
            MethodInfo method = (MethodInfo)keyMethod.Invoke(null, null);

            DebugUtils.Assert(method != null, "GetToObjectMethod Not Found Type2: " + type.FullName);
            GenericMethodInfos.Add(type, method);
            return(method);
        }
Пример #21
0
        public static object ToObject(string str, Type type)
        {
            if (type.IsGenericType)
            {
                if (type.GetGenericTypeDefinition() == typeof(List <>))
                {
                    Type[]        types  = type.GetGenericArguments();
                    Type          t      = types[0];
                    List <string> list   = ToListObject(str);
                    var           result = type.GetConstructor(Type.EmptyTypes).Invoke(null);
                    foreach (var item in list)
                    {
                        var v = ToObject(item, t);
                        ListAddMethodInfo.Invoke(result, new object[] { v });
                    }
                    return(result);
                }
                else if (type.GetGenericTypeDefinition() == typeof(Dictionary <,>))
                {
                    Type[] types = type.GetGenericArguments();
                    Dictionary <string, string> map = ToMapObject(str);
                    var result = type.GetConstructor(Type.EmptyTypes).Invoke(null);
                    foreach (var item in map)
                    {
                        var key = ToObject(item.Key, types[0]);
                        var v   = ToObject(item.Value, types[1]);
                        DictionaryAddMethodInfo.Invoke(result, new object[] { key, v });
                    }
                    return(result);
                }
                DebugUtils.Assert(false, "ToObject Not Found Type: " + type.FullName);
                return(null);
            }
            else if (type.BaseType == typeof(Enum))
            {
                return(EnumUtils.StringToEnum(str, type));
            }
            MethodInfo method = GetToObjectMethodInfoFromCache(type);

            GenericParametersObjectTwo[0] = str;
            GenericParametersObjectTwo[1] = GetDefault(type);
            bool res = (bool)method.Invoke(null, GenericParametersObjectTwo);

            DebugUtils.Assert(res, string.Format("Data {0} Not Right Type {1}", str, type.FullName));
            return(GenericParametersObjectTwo[1]);
        }
Пример #22
0
        /// <summary>
        /// 此时还未添加到 mBuffs 容器
        /// </summary>
        /// <param name="bufferId"></param>
        /// <param name="caster"></param>
        /// <param name="ability"></param>
        /// <returns></returns>
        public bool CreateBuff(int bufferId, object caster, object ability)
        {
            // 获取Buff配置信息
            BuffData data = BuffData.Get(bufferId);

            DebugUtils.Assert(data != null, "bufferId " + bufferId);
            // 被免疫,不添加
            if (IsImmune(data.BuffTag))
            {
                return(false);
            }
            // Buff实例化
            Buff buff = new Buff(data, this, caster, ability);

            OnBuffAwake?.Invoke(buff);
            return(true);
        }
Пример #23
0
 // string格式有要求
 public static DateTime GetTime(string dtStr)
 {
     dtStr = dtStr.Trim();
     dtStr = dtStr.Replace("/", "-");
     string[] strs = dtStr.Split(new char[] { '-', ':', ' ' });
     if (strs.Length == 3)
     {
         dtStr = string.Format("{0} 00:00:00", dtStr);
     }
     try
     {
         return(Convert.ToDateTime(dtStr));
     }
     catch (Exception e)
     {
         DebugUtils.Assert(false, string.Format("Error: {0}, {1} Please Use 'yyyy-MM-dd[| HH:mm:ss]'", e.Message, dtStr)); // yyyy-MM-dd HH:mm:ss
     }
     return(default(DateTime));
 }
Пример #24
0
        public void Release(ObjectBase obj)
        {
            if (obj == null)
            {
                return;
            }
            Type type = obj.GetType();

            DebugUtils.Assert(type.IsSubclassOf(typeof(ObjectBase)), "wrong type");
            if (mPools.ContainsKey(type))
            {
                mPools[type].Release(obj);
            }
            else
            {
                // 释放调用 Destroy,比Release要强
                obj.Destroy();
            }
        }
Пример #25
0
        /// <summary>
        /// 加载一个AB资源
        /// </summary>
        /// <param name="bundleName">报名</param>
        /// <param name="isDependence">主包还是依赖包</param>
        /// <param name="isAsync">异步还是同步</param>
        /// <returns></returns>
        private Bundle CreateBundle(string bundleName, bool isDependence, bool isAsync)
        {
            DebugUtils.Assert(!IsContain(bundleName), "");
            Bundle bundle = null;

            if (isAsync)
            {
                bundle = new Bundle(bundleName, null);
                bundle.IsAsyncLoading = true;
                AssetBundleCreateRequest createRequest = AssetBundle.LoadFromFileAsync(FormatAbPath(bundleName));
                createRequest.completed += (asyncOperation) =>
                {
                    DebugUtils.Assert(asyncOperation.isDone, "wrong " + bundleName);
                    // 可能此时已被销毁,重新获取一下
                    Bundle cacheBundle = GetBundle(bundleName);
                    if (cacheBundle != null)
                    {
                        if (cacheBundle.Ab == null)
                        {
                            cacheBundle.Ab = createRequest.assetBundle;
                        }
                        bundle.IsAsyncLoading = false;
                    }
                    else
                    {
                        // 卸载
                        createRequest.assetBundle.Unload(true);
                    }
                    RemoveAsyncOperation(bundleName);
                };
                AddAsyncOperation(bundleName, createRequest);
            }
            else
            {
                AssetBundle ab = AssetBundle.LoadFromFile(FormatAbPath(bundleName));
                bundle = new Bundle(bundleName, ab);
                bundle.IsAsyncLoading = false;
            }
            bundle.IsLoadedByDpendenced = isDependence;
            mBundleCaches.Add(bundleName, bundle);
            return(bundle);
        }
Пример #26
0
 public static Properties GetPropertiesFromNamespacePath(Properties properties, List <string> namespacePath)
 {
     if (namespacePath.Count > 0)
     {
         int size = namespacePath.Count;
         properties.Rewind();
         Properties iter = properties.GetNextNamespace();
         for (int i = 0; i < size;)
         {
             while (true)
             {
                 if (iter == null)
                 {
                     DebugUtils.Assert(false, "Failed to load properties object from url.");
                     return(null);
                 }
                 if (namespacePath[i].Equals(iter.GetId())) // id, not namespace
                 {
                     if (i != size - 1)
                     {
                         properties = iter.GetNextNamespace();
                         iter.Rewind();
                         iter = properties;
                     }
                     else
                     {
                         properties = iter;
                     }
                     i++;
                     break;
                 }
                 iter = properties.GetNextNamespace();
             }
         }
         properties.Rewind();
         return(properties);
     }
     return(properties);
 }
Пример #27
0
        private string MakeClassDefine()
        {
            GameDataManagerType type = GameDataManagerType.LIST;

            if (Manager != null)
            {
                type = EnumUtils.StringToEnum <GameDataManagerType>(Manager.ToUpper());
            }
            string baseName = GetDataManager();

            if (type == GameDataManagerType.LIST)
            {
                return(string.Format("public class {0} : {1}<{2}>", SheetName, baseName, SheetName));
            }
            DebugUtils.Assert(!string.IsNullOrEmpty(Keys), "Wrong Keys");
            List <string> keys           = new List <string>(Keys.Split(','));
            string        dataTypeString = null;
            string        readString     = null;
            string        writeString    = null;
            string        generic        = string.Format("public class {0} : {1}<", SheetName, baseName);

            for (int j = 0; j < keys.Count; ++j)
            {
                string key = keys[j];
                int    i   = 0;
                for (i = 0; i < mVariableNames.Count; ++i)
                {
                    if (mVariableNames[i] == key)
                    {
                        break;
                    }
                }
                DebugUtils.Assert(i < mVariableNames.Count, string.Format("{0} KeyName Not Found", key));
                GetType(mVariableTypes[i], ref dataTypeString, ref readString, ref writeString);
                generic += dataTypeString + ", ";
            }
            generic += SheetName + ">";
            return(generic);
        }
Пример #28
0
        public static Properties CreateFromContent(string content, string urlString)
        {
            if (string.IsNullOrEmpty(content))
            {
                DebugUtils.Assert(false, "Attempting to create a Properties object from an empty URL!");
                return(null);
            }
            // Calculate the file and full namespace path from the specified url.
            string        fileString    = null;
            List <string> namespacePath = new List <string>();

            if (urlString != null)
            {
                CalculateNamespacePath(ref urlString, ref fileString, namespacePath);
            }
            using (NullMemoryStream stream = NullMemoryStream.ReadTextFromString(content))
            {
                Properties properties = new Properties(stream);
                properties.ResolveInheritance(null);
                // Get the specified properties object.
                Properties p = GetPropertiesFromNamespacePath(properties, namespacePath);
                if (p == null)
                {
                    DebugUtils.Assert(false, string.Format("Failed to load properties from url {0}.", urlString));
                    return(null);
                }
                if (p != properties)
                {
                    p = p.Clone();
                }
                if (fileString != null)
                {
                    p.SetDirectoryPath(Path.GetDirectoryName(fileString));
                }
                p.Rewind();
                return(p);
            }
        }
Пример #29
0
        /// <summary>
        /// 不支持 List 嵌套 其他 集合 类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="target"></param>
        /// <returns></returns>
        public static string ToXml <T>(List <T> target)
        {
            DebugUtils.Assert(!typeof(T).IsGenericType, "");
            string          name = typeof(T).Name;
            SecurityElement root = new SecurityElement(name + "s");

            PropertyInfo[] infos = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            foreach (T t in target)
            {
                SecurityElement child = new SecurityElement(name);
                root.AddChild(child);
                foreach (PropertyInfo info in infos)
                {
                    object value    = info.GetValue(t, null);
                    object defaultV = GetDefault(info.PropertyType);
                    if (value != null && !value.Equals(defaultV))
                    {
                        string v = ToString(value);
                        child.AddAttribute(info.Name, v);
                    }
                }
            }
            return(root.ToString());
        }
Пример #30
0
        private IEnumerator DownloadAssetBundles()
        {
            using (UnityWebRequest req = UnityWebRequest.Get(SystemConfig.GetFilePath("/", AssetbundleInfoFile, false)))
            {
                UnityWebRequestAsyncOperation reqBin = req.SendWebRequest();
                yield return(reqBin);

                if (req.isNetworkError || req.isHttpError)
                {
                    // 重新下载
                    DebugUtils.Log(InfoType.Error, string.Format("DiffAssets : {0}", SystemConfig.GetFilePath("/", AssetbundleInfoFile, false)));
                }
                else
                {
                    if (req.downloadHandler.isDone)
                    {
                        GameDataManager.ChangeDir(SystemConfig.GameDataDir);
                        // 本地获取并解析, 全部拷贝一份
                        List <AssetbundleUpdateData> oldDataInfos = AssetbundleUpdateData.Select((item) => { return(item.Name != null); });
                        // 清理不存在本地文件的实例
                        int notExistsCount = oldDataInfos.RemoveAll((item) => { return(IsFileExist(item)); });
                        DebugUtils.Log(InfoType.Warning, string.Format("notExistsCount {0}", notExistsCount));
                        // 再释放
                        GameDataManager.ClearFileData(AssetbundleInfoFile);
                        DebugUtils.Assert(AssetbundleUpdateData.IsOriginNull(), "wrong clear");
                        // 保存到 临时目录
                        string text = req.downloadHandler.text;
                        File.WriteAllText(SystemConfig.LocalTempDir + "/" + AssetbundleInfoFile, text);
                        // 切换到 临时目录
                        GameDataManager.ChangeDir(SystemConfig.LocalTempDir);
                        // 全部拷贝一份
                        List <AssetbundleUpdateData> newDataInfos = AssetbundleUpdateData.Select((item) => { return(item.Name != null); });
                        // 释放
                        GameDataManager.ClearFileData(AssetbundleInfoFile);
                        DebugUtils.Assert(AssetbundleUpdateData.IsOriginNull(), "wrong clear");
                        GameDataManager.ChangeDir(SystemConfig.GameDataDir);
                        // 处理
                        List <AssetbundleUpdateData> addAssets = DiffAssetBundles(oldDataInfos, newDataInfos);
                        mDownloadSize  = 0;
                        mTotalSize     = 0;
                        mTotalCount    = 0;
                        mDownloadCount = 0;
                        mAssetbunlesWebRequest.Clear();
                        mTotalCount = addAssets.Count;
                        addAssets.ForEach((item) => { mTotalSize += item.FileSize; });
                        foreach (AssetbundleUpdateData info in addAssets)
                        {
                            string          url   = SystemConfig.GetRemotePathInAssetbundle(info.Name);
                            UnityWebRequest abReq = UnityWebRequest.Get(url);
                            AddReq(abReq);
                            UnityWebRequestAsyncOperation reqAssetbundleReq = abReq.SendWebRequest();
                            reqAssetbundleReq.completed += (AsyncOperation operation) =>
                            {
                                if (abReq.isNetworkError || abReq.isHttpError)
                                {
                                    // 重新下载
                                    DebugUtils.Log(InfoType.Error, "wrong req: " + url);
                                }
                                else
                                {
                                    AddDownloadCount();
                                    byte[] data = abReq.downloadHandler.data;
                                    AddDownloadSize(data.Length);
                                    SaveLocalAssetBundle(info.Name, data);
                                    // 下载进度
                                    SizeProgress?.Invoke(SizePercent);
                                    CountProgress?.Invoke(mDownloadCount, mTotalCount);
                                }
                                RemoveReq(abReq);
                                abReq.Dispose();
                            };
                        }

                        // 开始进度
                        SizeProgress?.Invoke(SizePercent);
                        while (mAssetbunlesWebRequest.Count > 0)
                        {
                            yield return(Wait);
                        }

                        Finished?.Invoke(mVersionData.InfoTips);
                    }
                }
            }
        }