protected void FixedUpdate()
        {
            BeginFrame();

            float deltaTime = Time.fixedDeltaTime;

            for (int iBehaviour = 0; iBehaviour < m_BehavioursForTraverse.Count; iBehaviour++)
            {
                BaseBehaviour iterBehaviour = m_BehavioursForTraverse[iBehaviour];
                if (!iterBehaviour.CanUpdate())
                {
                    continue;
                }

                try
                {
                    MDebug.LogVerbose("Core"
                                      , $"Before execute {iterBehaviour.GetName()}.OnFixedUpdate");

                    iterBehaviour.OnFixedUpdate(deltaTime);

                    MDebug.LogVerbose("Core"
                                      , $"After execute {iterBehaviour.GetName()}.OnFixedUpdate");
                }
                catch (Exception e)
                {
                    MDebug.LogError("Core"
                                    , $"Execute {iterBehaviour.GetName()}.OnFixedUpdate Exception:{e.ToString()}");
                }
            }
        }
        private void SafeInvoke(int eventId, bool isImmediately, IUserData userData)
        {
            EventFunction listener = m_Listeners[eventId];

            if (listener == null)
            {
                MDebug.LogVerbose("EventCenter", $"Event ({m_EventIdToName[eventId]}) not have listener.");
                if (userData is IObjectPoolItem poolItem)
                {
                    Kernel.ObjectPool.Release(poolItem);
                }
                return;
            }

            try
            {
                MDebug.LogVerbose("EventCenter"
                                  , $"Event ({m_EventIdToName[eventId]}) begin invoke.");

                listener.Invoke(eventId, isImmediately, userData);
                if (userData is IObjectPoolItem poolItem)
                {
                    Kernel.ObjectPool.Release(poolItem);
                }

                MDebug.LogVerbose("EventCenter"
                                  , $"Event ({m_EventIdToName[eventId]}) end invoke.");
            }
            catch (Exception e)
            {
                MDebug.LogError("EventCenter"
                                , $"Event ({m_EventIdToName[eventId]}) invoke Exception:\n{e.ToString()}");
            }
        }
        private void EndFrame()
        {
            TaskUpdate(Time.deltaTime);

            #region Handle Disable
            for (int iBehaviour = 0; iBehaviour < m_BehavioursForTraverse.Count; iBehaviour++)
            {
                BaseBehaviour behaviour = m_BehavioursForTraverse[iBehaviour];
                DisableBehaviour(behaviour);
            }
            #endregion

            #region Handle Release
            for (int iBehaviour = 0; iBehaviour < m_RemoveBehavioursCache.Count; iBehaviour++)
            {
                BaseBehaviour behaviour = m_RemoveBehavioursCache[iBehaviour];
                ReleaseBehaviour(behaviour);
            }
            m_RemoveBehavioursCache.Clear();
            #endregion

            m_BehavioursForTraverse.Clear();

            MDebug.LogVerbose("Core", "EndFrame " + Time.frameCount);
        }
            public AssetAction RemoveReference()
            {
                MDebug.LogVerbose(LOG_TAG, $"Asset Remove Reference:{m_AssetKey}, Reference Count: {m_ReferenceCount}");
                MDebug.Assert(m_ReferenceCount > 0, LOG_TAG, "m_ReferenceCount = 0 cant remove");
                if (m_ReferenceCount == 0)
                {
                    return(AssetAction.Null);
                }
                m_ReferenceCount--;
                switch (m_AssetState)
                {
                case AssetState.WaitLoad:
                case AssetState.Loading:
                    MDebug.Assert(false, LOG_TAG, "Asset Not Load But Remove Reference");
                    return(AssetAction.Null);

                case AssetState.Loaded:
                    if (m_ReferenceCount == 0)
                    {
                        m_AssetState = AssetState.NeedUnload;
                        return(AssetAction.Unload);
                    }
                    else
                    {
                        return(AssetAction.Null);
                    }

                default:
                    MDebug.Assert(false, LOG_TAG, "Asset Not Support AssetState");
                    return(AssetAction.Null);
                }
            }
        private void DisableBehaviour(BaseBehaviour behaviour)
        {
            if (!behaviour.IsEnable() && behaviour.IsLastEnable())
            {
                try
                {
                    MDebug.LogVerbose("Core"
                                      , $"Before execute {behaviour.GetName()}.OnDisable");

                    behaviour.OnDisable();

                    MDebug.LogVerbose("Core"
                                      , $"After execute {behaviour.GetName()}.OnDisable");
                }
                catch (Exception e)
                {
                    MDebug.LogError("Core"
                                    , $"Execute {behaviour.GetName()}.OnDisable Exception:{e.ToString()}");
                }
                finally
                {
                    behaviour.SetLastEnable(false);
                }
            }
        }
            public BundleAction RemoveReference()
            {
                MDebug.LogVerbose(LOG_TAG, $"Bundle Remove Reference:{ms_AssetManager.m_BundleInfos[m_BundleIndex].BundleName}, Reference Count: {m_ReferenceCount}");
                MDebug.Assert(m_ReferenceCount > 0, LOG_TAG, "m_ReferenceCount = 0, Cant Remove!");
                m_ReferenceCount--;
                switch (m_BundleState)
                {
                case BundleState.NotLoad:
                case BundleState.NeedLoad:
                    MDebug.Assert(false, LOG_TAG, "BundleState.NotLoad");
                    return(BundleAction.Null);

                case BundleState.Loaded:
                    if (m_ReferenceCount == 0)
                    {
                        m_BundleState = BundleState.NeedUnload;
                        return(BundleAction.Unload);
                    }
                    else
                    {
                        return(BundleAction.Null);
                    }

                case BundleState.Loading:
                    MDebug.Assert(m_ReferenceCount > 0, LOG_TAG, "m_ReferenceCount > 0");
                    return(BundleAction.Null);

                default:
                    MDebug.Assert(false, LOG_TAG, "Not support BundleState: " + m_BundleState);
                    return(BundleAction.Null);
                }
            }
            public AssetAction AddReference(Action <AssetKey, UnityEngine.Object> callback)
            {
                m_OnAssetLoaded += callback;
                m_ReferenceCount++;

                MDebug.LogVerbose(LOG_TAG, $"Asset Add Reference:{m_AssetKey}, Reference Count: {m_ReferenceCount}");

                switch (m_AssetState)
                {
                case AssetState.Loaded:
                    MDebug.Assert(m_Asset != null, LOG_TAG, "m_Asset != null");
                    return(AssetAction.LoadedCallback);

                case AssetState.NotLoad:
                    m_AssetState = AssetState.WaitLoad;
                    return(AssetAction.RequestLoadBundle);

                case AssetState.WaitLoad:
                case AssetState.Loading:
                    return(AssetAction.Null);

                case AssetState.NeedUnload:
                    MDebug.Assert(m_Asset != null, LOG_TAG, "m_Asset != null");
                    m_AssetState = AssetState.Loaded;
                    return(AssetAction.LoadedCallback);

                default:
                    MDebug.Assert(false, LOG_TAG, "Asset Not Support AssetState");
                    return(AssetAction.Null);
                }
            }
            public BundleAction AddReference()
            {
                m_ReferenceCount++;

                MDebug.LogVerbose(LOG_TAG, $"Bundle Add Reference:{ms_AssetManager.m_BundleInfos[m_BundleIndex].BundleName}, Reference Count: {m_ReferenceCount}");

                switch (m_BundleState)
                {
                case BundleState.NotLoad:
                    m_BundleState = BundleState.NeedLoad;
                    return(BundleAction.Load);

                case BundleState.Loaded:
                case BundleState.Loading:
                case BundleState.NeedLoad:
                    return(BundleAction.Null);

                case BundleState.NeedUnload:
                    m_BundleState = BundleState.Loaded;
                    return(BundleAction.Null);

                default:
                    MDebug.Assert(false, LOG_TAG, "Not support BundleState: " + m_BundleState);
                    return(BundleAction.Null);
                }
            }
        /// <summary>
        /// 包含Bundle是否需要加载判断,添加资源引用计数,并在尚未加载Bundle时,设置加载完成时回调
        /// </summary>
        /// <param name="bundleIndex"></param>
        /// <param name="assetIndex"></param>
        private void LoadBundleForLoadAsset(int bundleIndex, int assetIndex)
        {
            BundleHandler bundleHandler = m_BundleHandlers[bundleIndex];

            if (bundleHandler == null)
            {
                bundleHandler = m_BundleHandlerPool.Alloc();
                bundleHandler.SetBundleIndex(bundleIndex);
                m_BundleHandlers[bundleIndex] = bundleHandler;
            }

            BundleAction bundleAction = bundleHandler.AddReference();

            if (bundleAction == BundleAction.Load)
            {
                m_BundleActionRequests.Enqueue(new BundleActionRequest(bundleIndex, bundleAction));

                MDebug.LogVerbose(LOG_TAG, $"Add load bundle action. Bundle:({m_BundleInfos[bundleIndex].BundleName}) Asset:({(AssetKey)assetIndex})");
            }
            else if (bundleAction == BundleAction.Null)
            {
                // Dont need handle
            }
            else
            {
                MDebug.Assert(false, "AsestBundle", "Not support BundleAction: " + bundleAction);
            }

            bundleHandler.TryAddDependencyAsset(m_AssetHandlers[assetIndex]);
        }
        /// <summary>
        /// 等待所有的<see cref="TaskUpdate"/>完成
        /// </summary>
        private void WaitTaskUpdate()
        {
            for (int iTask = 0; iTask < m_TaskItemsCache.Count; iTask++)
            {
                TaskUpdateItem taskItem = m_TaskItemsCache[iTask];
                taskItem.ManualResetEvent.WaitOne();

                BaseBehaviour iterBehaviour = taskItem.Behaviour;
                try
                {
                    MDebug.LogVerbose("Core"
                                      , $"Before execute {iterBehaviour.GetName()}.OnAfterTaskUpdate");

                    iterBehaviour.OnAfterTaskUpdate(taskItem.Output);

                    MDebug.LogVerbose("Core"
                                      , $"After execute {iterBehaviour.GetName()}.OnAfterTaskUpdate");
                }
                catch (Exception e)
                {
                    MDebug.LogError("Core"
                                    , $"Execute {iterBehaviour.GetName()}.OnAfterTaskUpdate Exception:{e.ToString()}");
                }

                m_TaskItemPool.Release(taskItem);
            }

            m_TaskItemsCache.Clear();
        }
        private int PointToGridIndex(Vector2 point)
        {
            int indexX = (int)(point.x / m_CellSize);
            int indexY = (int)(point.y / m_CellSize);

            MDebug.LogVerbose("Sampling", $"PointToGridIndex({point}) indexX({indexX}) indexY({indexY})");
            return(indexX + indexY * m_YCellCount);
        }
        protected void Update()
        {
            // 这里也要调用一次的原因是,当前帧可能没执行FixedUpdate
            BeginFrame();

            float deltaTime  = Time.deltaTime;
            int   frameCount = Time.frameCount;

            ParallelUpdate(deltaTime);

            for (int iBehaviour = 0; iBehaviour < m_BehavioursForTraverse.Count; iBehaviour++)
            {
                BaseBehaviour iterBehaviour = m_BehavioursForTraverse[iBehaviour];
                if (!iterBehaviour.CanUpdate())
                {
                    continue;
                }

                float behaviourDeltaTime;
                if (iterBehaviour.HasFeature(FeatureFlag.UpdateFrequency))
                {
                    try
                    {
                        if (!iterBehaviour.ControlUpdateFrequency(out behaviourDeltaTime, deltaTime, frameCount))
                        {
                            continue;
                        }
                    }
                    catch (Exception e)
                    {
                        MDebug.LogError("Core"
                                        , $"Execute {iterBehaviour.GetName()}.ControlUpdateFrequency Exception:{e.ToString()}");
                        continue;
                    }
                }
                else
                {
                    behaviourDeltaTime = deltaTime;
                }

                try
                {
                    MDebug.LogVerbose("Core"
                                      , $"Before execute {iterBehaviour.GetName()}.OnUpdate");

                    iterBehaviour.OnUpdate(behaviourDeltaTime);

                    MDebug.LogVerbose("Core"
                                      , $"After execute {iterBehaviour.GetName()}.OnUpdate");
                }
                catch (Exception e)
                {
                    MDebug.LogError("Core"
                                    , $"Execute {iterBehaviour.GetName()}.OnUpdate Exception:{e.ToString()}");
                }
            }
        }
        private static int Verbose(IntPtr luaState)
        {
            int success = GetLog(luaState, out string tag, out string message);

            if (success == 1)
            {
                MDebug.LogVerbose(tag, message);
            }

            return(success);
        }
        private void ReleaseBehaviour(BaseBehaviour behaviour)
        {
            try
            {
                MDebug.LogVerbose("Core"
                                  , $"Before execute {behaviour.GetName()}.OnRelease");

                behaviour.OnRelease();

                MDebug.LogVerbose("Core"
                                  , $"After execute {behaviour.GetName()}.OnRelease");
            }
            catch (Exception e)
            {
                MDebug.LogError("Core"
                                , $"Execute {behaviour.GetName()}.OnRelease Exception:{e.ToString()}");
            }
        }
示例#15
0
        private void ProcessReceive(object sender, SocketAsyncEventArgs e)
        {
            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                MDebug.LogVerbose(LOG_TAG
                                  , $"Client({GetName()}) 接收长度: {e.BytesTransferred}");

                OnReceived(m_ReceiveBuffer.GetBuffer()
                           , m_ReceiveBuffer.GetOffset()
                           , e.BytesTransferred);

                StartReceive();
            }
            else
            {
                MDebug.LogError(LOG_TAG
                                , $"Client({GetName()}) 接受消息失败: {e.SocketError.ToString()}, 即将断开连接。{e.BytesTransferred}|{e.SocketError}");
                Disconnect(e);
            }
        }
示例#16
0
        /// <summary>
        /// 对<see cref="OnTaskUpdate_Thread"/>的一层封装
        ///     错误处理
        ///     处理<see cref="System.Threading.ManualResetEvent"/>
        /// </summary>
        internal void DoTaskUpdate_Thread(object state)
        {
            TaskUpdateItem taskItem = state as TaskUpdateItem;

            try
            {
                MDebug.LogVerbose("Core"
                                  , $"Before execute {GetName()}.OnTaskUpdate_Thread");

                taskItem.Output = OnTaskUpdate_Thread(taskItem.Input, taskItem.DeltaTime);

                MDebug.LogVerbose("Core"
                                  , $"After execute {GetName()}.OnTaskUpdate_Thread");
            }
            catch (Exception e)
            {
                MDebug.LogError("Core"
                                , $"Execute {GetName()}.OnTaskUpdate_Thread Exception:{e.ToString()}");
            }

            taskItem.ManualResetEvent.Set();
        }
示例#17
0
        public override object OnTaskUpdate_Thread(object input, float deltaTime)
        {
            unsafe
            {
                int   bufferLength = CallLuaAPI.lua_gfloginternal_getbufferlength();
                byte *logBuffer    = (byte *)CallLuaAPI.lua_gfloginternal_getbuffer().ToPointer();
                CallLuaAPI.lua_gfloginternal_swapbuffer();
                while (bufferLength > 0)
                {
                    logBuffer = ConvertToIntFromLogBuffer(logBuffer, ref bufferLength, out int type);
                    logBuffer = ConvertToStringFromLogBuffer(logBuffer, ref bufferLength, out string tag);
                    logBuffer = ConvertToStringFromLogBuffer(logBuffer, ref bufferLength, out string message);

                    switch (type)
                    {
                    case LOGTYPE_VERBOSE:
                        MDebug.LogVerbose(tag, message);
                        break;

                    case (int)LogType.Log:
                        MDebug.Log(tag, message);
                        break;

                    case (int)LogType.Warning:
                        MDebug.LogWarning(tag, message);
                        break;

                    case (int)LogType.Error:
                        MDebug.LogError(tag, message);
                        break;

                    default:
                        throw new Exception("Not handle LogType: " + type);
                    }
                }
            }
            return(null);
        }
示例#18
0
        /// <summary>
        /// 减少指定Bundle包中的资源引用计数
        /// </summary>
        /// <param name="bundleIndex"></param>
        private void RemoveAssetDependency(int bundleIndex, int assetIndex)
        {
            BundleHandler bundleHandler = m_BundleHandlers[bundleIndex];

            if (bundleHandler != null)
            {
                BundleAction bundleAction = bundleHandler.RemoveReference();
                if (bundleAction == BundleAction.Unload)
                {
                    m_BundleActionRequests.Enqueue(new BundleActionRequest(bundleIndex, bundleAction));

                    MDebug.LogVerbose(LOG_TAG, $"Add remove bundle action. Bundle:({m_BundleInfos[bundleIndex].BundleName}) Asset:({(AssetKey)assetIndex})");
                }
                else if (bundleAction == BundleAction.Null)
                {
                    // Dont need handle
                }
                else
                {
                    MDebug.Assert(false, "AsestBundle", "Not support BundleAction: " + bundleAction);
                }
            }
        }
        private void TaskUpdate(float deltaTime)
        {
            MDebug.Assert(m_TaskItemsCache.Count == 0, "Core", "m_TaskItemsCache.Count == 0");

            for (int iBehaviour = 0; iBehaviour < m_BehavioursForTraverse.Count; iBehaviour++)
            {
                BaseBehaviour iterBehaviour = m_BehavioursForTraverse[iBehaviour];
                if (!iterBehaviour.CanUpdate() ||
                    !iterBehaviour.HasFeature(FeatureFlag.TaskUpdate))
                {
                    continue;
                }

                TaskUpdateItem iterTaskItem = m_TaskItemPool.Alloc()
                                              .SetData(iterBehaviour, deltaTime);
                m_TaskItemsCache.Add(iterTaskItem);

                try
                {
                    MDebug.LogVerbose("Core"
                                      , $"Before execute {iterBehaviour.GetName()}.OnBeforeTastUpdate");

                    iterTaskItem.Input = iterBehaviour.OnBeforeTastUpdate();

                    MDebug.LogVerbose("Core"
                                      , $"After execute {iterBehaviour.GetName()}.OnBeforeTastUpdate");
                }
                catch (Exception e)
                {
                    MDebug.LogError("Core"
                                    , $"Execute {iterBehaviour.GetName()}.OnBeforeTastUpdate Exception:{e.ToString()}");
                }

                System.Threading.ThreadPool.QueueUserWorkItem(iterBehaviour.DoTaskUpdate_Thread, iterTaskItem);
            }
        }
示例#20
0
        public Node AllocBuffer(int size)
        {
            MDebug.Assert(size > 0
                          , "ArrayPool"
                          , "size > 0");

            Node iterNode = m_Root;

#if GF_DEBUG
            int remainTime = 10000;
#endif
            while (true)
            {
#if GF_DEBUG
                if (remainTime-- == 0)
                {
                    throw new Exception("代码逻辑可能写错了");
                }
#endif

                // 可以在当前Node分配
                if (!iterNode.IsUsed() &&
                    iterNode.GetSize() >= size)
                {
                    int  remainSize = iterNode.GetSize() - size;
                    Node afterNode  = iterNode._After;
                    // 处理分配后的剩余空间
                    if (remainSize != 0)
                    {
                        // 不能和下一个Node合并,把剩余空间当成一个新的Node
                        if (afterNode == null ||
                            afterNode.IsUsed())
                        {
                            afterNode = ms_NodePool.Alloc().SetData(this
                                                                    , iterNode.GetOffset() + size
                                                                    , remainSize
                                                                    , false
                                                                    , iterNode
                                                                    , afterNode);
                            iterNode._After = afterNode;
                            if (afterNode._After != null)
                            {
                                afterNode._After._Before = afterNode;
                            }
                        }
                        // 剩余空间合并到下一个Node
                        else
                        {
#if GF_DEBUG
                            MDebug.Assert(afterNode.GetOffset() - iterNode.GetSize() == iterNode.GetOffset()
                                          , "ArrayPool"
                                          , "afterNode.GetOffset() - iterNode.GetSize() == iterNode.GetOffset()");
#endif
                            afterNode.SetData(this
                                              , iterNode.GetOffset() + size
                                              , afterNode.GetSize() + remainSize
                                              , false
                                              , afterNode._Before
                                              , afterNode._After);
                        }
                    }

                    iterNode.SetData(this
                                     , iterNode.GetOffset()
                                     , size
                                     , true
                                     , iterNode._Before
                                     , iterNode._After);
                    break;
                }

                // 寻找下一个Node
                if (iterNode._After != null)
                {
                    iterNode = iterNode._After;
                }
                // iterNode是LastNode,尝试扩容
                else
                {
                    // 扩容后空间肯定能分配一个size的Buffer
                    EnsureCapacity(m_Buffer.Length + size);
                    // 最后一个Node已经被使用了,分配一个新Node
                    if (iterNode.IsUsed())
                    {
                        iterNode = ms_NodePool.Alloc().SetData(this
                                                               , iterNode.GetOffset() + iterNode.GetSize()
                                                               , size
                                                               , true
                                                               , iterNode
                                                               , null);
                        iterNode._Before._After = iterNode;
                    }
                    // 把最后一个Node扩容成size大小
                    else
                    {
                        iterNode.SetData(this
                                         , iterNode.GetOffset()
                                         , size
                                         , true
                                         , iterNode._Before
                                         , null);
                    }

                    int lastOffset = iterNode.GetOffset() + iterNode.GetSize();
                    if (lastOffset < m_Buffer.Length)
                    {
                        // 把扩容后的剩余空间当成一个新Node
                        Node lastNode = ms_NodePool.Alloc().SetData(this
                                                                    , lastOffset
                                                                    , m_Buffer.Length - lastOffset
                                                                    , false
                                                                    , iterNode
                                                                    , null);
                        iterNode._After = lastNode;
                    }
                    break;
                }
            }

            MDebug.LogVerbose("ArrayPool"
                              , $"Alloc buffer offset:{iterNode.GetOffset()} size:{iterNode.GetSize()}");

            return(iterNode);
        }
        protected override void OnProcessShaderInternal(Shader shader
                                                        , ShaderSnippetData snippet
                                                        , IList <ShaderCompilerData> data)
        {
            #region Builtin
            bool isBuiltinShader = AssetUtility.IsBuiltinOrLibraryAsset(shader);
            if (isBuiltinShader)
            {
                m_BuiltinShaders[shader.name] = data.Count
                                                + (m_BuiltinShaders.TryGetValue(shader.name, out int count)
                        ? count
                        : 0);
            }
            #endregion

            #region ProcessInfo
            ProcessInfo processInfo = new ProcessInfo();
            processInfo.IsBuiltinShader = isBuiltinShader;
            processInfo.ShaderName      = shader.name;
            processInfo.ShaderType      = snippet.shaderType;
            processInfo.PassType        = snippet.passType;
            processInfo.PassName        = snippet.passName;

            processInfo.Compilers = new CompilerInfo[data.Count];
            Parallel.For(0, data.Count, (iShader) =>
            {
                processInfo.Compilers[iShader] = GenerateCompilerInfo(data[iShader]);
            });

            processInfo.Keywords = CollectionKeywords(processInfo.Compilers);
            #endregion

            #region Summary
            {
                string shaderName = (processInfo.IsBuiltinShader ? "B_" : "") + processInfo.ShaderName;
                if (!m_ShaderInfos.TryGetValue(shaderName, out ShaderInfo shaderInfo))
                {
                    shaderInfo = new ShaderInfo();
                    m_ShaderInfos.Add(shaderName, shaderInfo);
                }

                shaderInfo.ShaderTypes.Add(processInfo.ShaderType);
                shaderInfo.PassTypes.Add(processInfo.PassType);

                shaderInfo.VariantCount += processInfo.Compilers.Length;
                for (int iKeyword = 0; iKeyword < processInfo.Keywords.Length; iKeyword++)
                {
                    shaderInfo.Keywords.Add(processInfo.Keywords[iKeyword]);
                }
            }
            #endregion

            int index = ++m_HandledShader;
            Task.Run(() =>
            {
                try
                {
                    string directory = $"{m_ReportDirectory}/{(processInfo.IsBuiltinShader ? "B_" : "")}{StringUtility.FormatToFileName(processInfo.ShaderName)}/";
                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }

                    string processName = $"_({processInfo.ShaderType})_({processInfo.PassType})_({processInfo.PassName})_Count(";
                    string path        = $"{directory}{index}_{processName}{processInfo.Compilers.Length}).csv";
                    File.WriteAllText(path
                                      , GenerateCompilersReport(processInfo.Compilers, processInfo.Keywords));
                    MDebug.LogVerbose("Shader", "Save PreprocessShaderReport to path " + path);
                }
                catch (Exception e)
                {
                    MDebug.LogError("Shader"
                                    , "Save PreprocessShaderReport Exception:\n" + e.ToString());
                }
            });
        }
        private void BeginFrame()
        {
            if (Time.frameCount <= m_LastBeginFrame)
            {
                return;
            }
            m_LastBeginFrame = Time.frameCount;

            MDebug.LogVerbose("Core", "BeginFrame " + m_LastBeginFrame);
            WaitTaskUpdate();

            CollectionBehavioursForTraverse();

            #region Handle Initialize
            for (int iBehaviour = 0; iBehaviour < m_AddBehavioursCache.Count; iBehaviour++)
            {
                BaseBehaviour behaviour = m_AddBehavioursCache[iBehaviour];

                try
                {
                    MDebug.LogVerbose("Core"
                                      , $"Before execute {behaviour.GetName()}.OnInitialize");

                    behaviour.OnInitialize();

                    MDebug.LogVerbose("Core"
                                      , $"After execute {behaviour.GetName()}.OnInitialize");
                }
                catch (Exception e)
                {
                    MDebug.LogError("Core"
                                    , $"Execute {behaviour.GetName()}.OnInitialize Exception:{e.ToString()}");
                }
                behaviour.SetAlive(true);
            }
            m_AddBehavioursCache.Clear();
            #endregion

            #region Handle Enable
            for (int iBehaviour = 0; iBehaviour < m_BehavioursForTraverse.Count; iBehaviour++)
            {
                BaseBehaviour behaviour = m_BehavioursForTraverse[iBehaviour];
                if (behaviour.IsEnable() && !behaviour.IsLastEnable())
                {
                    try
                    {
                        MDebug.LogVerbose("Core"
                                          , $"Before execute {behaviour.GetName()}.OnEnable");

                        behaviour.OnEnable();

                        MDebug.LogVerbose("Core"
                                          , $"After execute {behaviour.GetName()}.OnEnable");
                    }
                    catch (Exception e)
                    {
                        MDebug.LogError("Core"
                                        , $"Execute {behaviour.GetName()}.OnEnable Exception:{e.ToString()}");
                    }
                    finally
                    {
                        behaviour.SetLastEnable(true);
                    }
                }
            }
            #endregion
        }
        private void ExecuteParallelUpdateGroup()
        {
            if (m_ParallelItemsCache.Count == 0)
            {
                return;
            }

            for (int iBehaviour = 0; iBehaviour < m_ParallelItemsCache.Count; iBehaviour++)
            {
                ParallelUpdateItem iterTask      = m_ParallelItemsCache[iBehaviour];
                BaseBehaviour      iterBehaviour = iterTask.Behaviour;

                try
                {
                    MDebug.LogVerbose("Core"
                                      , $"Before execute {iterBehaviour.GetName()}.OnBeforeParallelUpdate");

                    iterTask.Input = iterBehaviour.OnBeforeParallelUpdate(iterTask.DeltaTime);

                    MDebug.LogVerbose("Core"
                                      , $"After execute {iterBehaviour.GetName()}.OnBeforeParallelUpdate");
                }
                catch (Exception e)
                {
                    MDebug.LogError("Core"
                                    , $"Execute {iterBehaviour.GetName()}.OnBeforeParallelUpdate Exception:{e.ToString()}");
                }
            }

            System.Threading.Tasks.Parallel.For(0, m_ParallelItemsCache.Count, (iBehaviour) =>
            {
                ParallelUpdateItem iterTask = m_ParallelItemsCache[iBehaviour];
                BaseBehaviour iterBehaviour = iterTask.Behaviour;

                try
                {
                    MDebug.LogVerbose("Core"
                                      , $"Before execute {iterBehaviour.GetName()}.OnParallelUpdate_Thread");

                    iterTask.Output = iterBehaviour.OnParallelUpdate_Thread(iterTask.Input, iterTask.DeltaTime);

                    MDebug.LogVerbose("Core"
                                      , $"After execute {iterBehaviour.GetName()}.OnParallelUpdate_Thread");
                }
                catch (Exception e)
                {
                    MDebug.LogError("Core"
                                    , $"Execute {iterBehaviour.GetName()}.OnParallelUpdate_Thread Exception:{e.ToString()}");
                }
            });

            for (int iBehaviour = 0; iBehaviour < m_ParallelItemsCache.Count; iBehaviour++)
            {
                ParallelUpdateItem iterTask      = m_ParallelItemsCache[iBehaviour];
                BaseBehaviour      iterBehaviour = iterTask.Behaviour;

                try
                {
                    MDebug.LogVerbose("Core"
                                      , $"Before execute {iterBehaviour.GetName()}.OnAfterParallelUpdate");

                    iterBehaviour.OnAfterParallelUpdate(iterTask.Output, iterTask.DeltaTime);

                    MDebug.LogVerbose("Core"
                                      , $"After execute {iterBehaviour.GetName()}.OnAfterParallelUpdate");
                }
                catch (Exception e)
                {
                    MDebug.LogError("Core"
                                    , $"Execute {iterBehaviour.GetName()}.OnAfterParallelUpdate Exception:{e.ToString()}");
                }

                m_ParallelItemPool.Release(iterTask);
            }

            m_ParallelItemsCache.Clear();
        }