Explorar o código

TimerComponent跟CoroutineLockComponent改成Entity,但是Fiber中有这两个的EntityRef,方便加速获取

tanghai %!s(int64=2) %!d(string=hai) anos
pai
achega
979d6dae28

+ 26 - 6
Unity/Assets/Scripts/Core/Fiber/Fiber.cs

@@ -38,8 +38,32 @@ namespace ET
         public IdGenerater IdGenerater { get; private set; }
         public Mailboxes Mailboxes { get; private set; }
         public ThreadSynchronizationContext ThreadSynchronizationContext { get; }
-        public TimerComponent TimerComponent { get; }
-        public CoroutineLockComponent CoroutineLockComponent { get; }
+        
+        private EntityRef<TimerComponent> timerCompnent;
+        public TimerComponent TimerComponent
+        {
+            get
+            {
+                return this.timerCompnent;
+            }
+            set
+            {
+                this.timerCompnent = value;
+            }
+        }
+        
+        private EntityRef<CoroutineLockComponent> coroutineLockComponent;
+        public CoroutineLockComponent CoroutineLockComponent
+        {
+            get
+            {
+                return this.coroutineLockComponent;
+            }
+            set
+            {
+                this.coroutineLockComponent = value;
+            }
+        }
 
         private readonly Queue<ETTask> frameFinishTasks = new();
         
@@ -52,8 +76,6 @@ namespace ET
             this.TimeInfo = new TimeInfo();
             this.IdGenerater = new IdGenerater(process, this.TimeInfo);
             this.Mailboxes = new Mailboxes();
-            this.TimerComponent = new TimerComponent(this.TimeInfo);
-            this.CoroutineLockComponent = new CoroutineLockComponent(this.TimerComponent);
             this.ThreadSynchronizationContext = new ThreadSynchronizationContext();
             this.Root = new Scene(this, id, 1, sceneType, name);
         }
@@ -65,8 +87,6 @@ namespace ET
                 this.ThreadSynchronizationContext.Update();
                 this.TimeInfo.Update();
                 this.EntitySystem.Update();
-                this.TimerComponent.Update();
-                this.CoroutineLockComponent.Update();
             }
             catch (Exception e)
             {

+ 20 - 35
Unity/Assets/Scripts/Core/Fiber/Module/CoroutineLock/CoroutineLock.cs

@@ -2,46 +2,31 @@ using System;
 
 namespace ET
 {
-    public class CoroutineLock: IDisposable
+    public static partial class CoroutineLockSystem
     {
-        private CoroutineLockComponent coroutineLockComponent;
-        private int type;
-        private long key;
-        private int level;
-        
-        public static CoroutineLock Create(CoroutineLockComponent coroutineLockComponent, int type, long k, int count)
-        {
-            CoroutineLock coroutineLock = ObjectPool.Instance.Fetch<CoroutineLock>();
-            coroutineLock.coroutineLockComponent = coroutineLockComponent;
-            coroutineLock.type = type;
-            coroutineLock.key = k;
-            coroutineLock.level = count;
-            return coroutineLock;
-        }
-
-        public bool IsDisposed
+        [EntitySystem]
+        private static void Awake(this CoroutineLock self, int type, long k, int count)
         {
-            get
-            {
-                return this.coroutineLockComponent == null;
-            }
+            self.type = type;
+            self.key = k;
+            self.level = count;
         }
         
-        public void Dispose()
+        [EntitySystem]
+        private static void Destroy(this CoroutineLock self)
         {
-            if (this.IsDisposed)
-            {
-                return;
-            }
-            
-            coroutineLockComponent.RunNextCoroutine(this.type, this.key, this.level + 1);
-            
-            this.type = CoroutineLockType.None;
-            this.key = 0;
-            this.level = 0;
-            this.coroutineLockComponent = null;
-            
-            ObjectPool.Instance.Recycle(this);
+            self.Scene<CoroutineLockComponent>().RunNextCoroutine(self.type, self.key, self.level + 1);
+            self.type = CoroutineLockType.None;
+            self.key = 0;
+            self.level = 0;
         }
     }
+    
+    [ChildOf(typeof(CoroutineLockQueue))]
+    public class CoroutineLock: Entity, IAwake<int, long, int>, IDestroy
+    {
+        public int type;
+        public long key;
+        public int level;
+    }
 }

+ 26 - 25
Unity/Assets/Scripts/Core/Fiber/Module/CoroutineLock/CoroutineLockComponent.cs

@@ -3,28 +3,26 @@ using System.Collections.Generic;
 
 namespace ET
 {
-    public class CoroutineLockComponent
+    public static partial class CoroutineLockComponentSystem
     {
-        public readonly TimerComponent TimerComponent;
-        private readonly Dictionary<int, CoroutineLockQueueType> dictionary = new();
-        private readonly Queue<(int, long, int)> nextFrameRun = new();
-
-        public CoroutineLockComponent(TimerComponent timerComponent)
+        [EntitySystem]
+        public static void Awake(this CoroutineLockComponent self)
         {
-            this.TimerComponent = timerComponent;
+            self.Fiber.CoroutineLockComponent = self;
         }
-
-        public void Update()
+        
+        [EntitySystem]
+        public static void Update(this CoroutineLockComponent self)
         {
             // 循环过程中会有对象继续加入队列
-            while (this.nextFrameRun.Count > 0)
+            while (self.nextFrameRun.Count > 0)
             {
-                (int coroutineLockType, long key, int count) = this.nextFrameRun.Dequeue();
-                this.Notify(coroutineLockType, key, count);
+                (int coroutineLockType, long key, int count) = self.nextFrameRun.Dequeue();
+                self.Notify(coroutineLockType, key, count);
             }
         }
 
-        public void RunNextCoroutine(int coroutineLockType, long key, int level)
+        public static void RunNextCoroutine(this CoroutineLockComponent self, int coroutineLockType, long key, int level)
         {
             // 一个协程队列一帧处理超过100个,说明比较多了,打个warning,检查一下是否够正常
             if (level == 100)
@@ -32,29 +30,32 @@ namespace ET
                 Log.Warning($"too much coroutine level: {coroutineLockType} {key}");
             }
 
-            this.nextFrameRun.Enqueue((coroutineLockType, key, level));
+            self.nextFrameRun.Enqueue((coroutineLockType, key, level));
         }
 
-        public async ETTask<CoroutineLock> Wait(int coroutineLockType, long key, int time = 60000)
+        public static async ETTask<CoroutineLock> Wait(this CoroutineLockComponent self, int coroutineLockType, long key, int time = 60000)
         {
-            CoroutineLockQueueType coroutineLockQueueType;
-            if (!this.dictionary.TryGetValue(coroutineLockType, out coroutineLockQueueType))
-            {
-                coroutineLockQueueType = new CoroutineLockQueueType(this, coroutineLockType);
-                this.dictionary.Add(coroutineLockType, coroutineLockQueueType);
-            }
+            CoroutineLockQueueType coroutineLockQueueType = self.GetChild<CoroutineLockQueueType>(coroutineLockType) ?? self.AddChildWithId<CoroutineLockQueueType>(coroutineLockType);
             return await coroutineLockQueueType.Wait(key, time);
         }
 
-        private void Notify(int coroutineLockType, long key, int level)
+        private static void Notify(this CoroutineLockComponent self, int coroutineLockType, long key, int level)
         {
-            CoroutineLockQueueType coroutineLockQueueType;
-            if (!this.dictionary.TryGetValue(coroutineLockType, out coroutineLockQueueType))
+            CoroutineLockQueueType coroutineLockQueueType = self.GetChild<CoroutineLockQueueType>(coroutineLockType);
+            if (coroutineLockQueueType == null)
             {
                 return;
             }
-            
             coroutineLockQueueType.Notify(key, level);
         }
     }
+    
+    [ComponentOf(typeof(Scene))]
+    public class CoroutineLockComponent: Entity, IAwake, IScene, IUpdate
+    {
+        public Fiber Fiber { get; set; }
+        public SceneType SceneType { get; set; }
+        
+        public readonly Queue<(int, long, int)> nextFrameRun = new();
+    }
 }

+ 43 - 48
Unity/Assets/Scripts/Core/Fiber/Module/CoroutineLock/CoroutineLockQueue.cs

@@ -3,93 +3,88 @@ using System.Collections.Generic;
 
 namespace ET
 {
-    public class CoroutineLockQueue: IDisposable
+    public static partial class CoroutineLockQueueSystem
     {
-        private CoroutineLockComponent coroutineLockComponent;
-        private int type;
-        private long key;
-        
-        public static CoroutineLockQueue Create(CoroutineLockComponent coroutineLockComponent, int type, long key)
+        [EntitySystem]
+        private static void Awake(this CoroutineLockQueue self, int type)
         {
-            CoroutineLockQueue coroutineLockQueue = ObjectPool.Instance.Fetch<CoroutineLockQueue>();
-            coroutineLockQueue.coroutineLockComponent = coroutineLockComponent; 
-            coroutineLockQueue.type = type;
-            coroutineLockQueue.key = key;
-            return coroutineLockQueue;
+            self.type = type;
         }
-
-        private CoroutineLock currentCoroutineLock;
         
-        private readonly Queue<WaitCoroutineLock> queue = new Queue<WaitCoroutineLock>();
-
-        public int Count
+        [EntitySystem]
+        private static void Destroy(this CoroutineLockQueue self)
         {
-            get
-            {
-                return this.queue.Count;
-            }
+            self.queue.Clear();
+            self.type = 0;
+            self.CurrentCoroutineLock = null;
         }
-
-        public async ETTask<CoroutineLock> Wait(int time)
+        
+        public static async ETTask<CoroutineLock> Wait(this CoroutineLockQueue self, int time)
         {
-            if (this.currentCoroutineLock == null)
+            if (self.CurrentCoroutineLock == null)
             {
-                this.currentCoroutineLock = CoroutineLock.Create(this.coroutineLockComponent, type, key, 1);
-                return this.currentCoroutineLock;
+                self.CurrentCoroutineLock = self.AddChild<CoroutineLock, int, long, int>(self.type, self.Id, 1, true);
+                return self.CurrentCoroutineLock;
             }
 
             WaitCoroutineLock waitCoroutineLock = WaitCoroutineLock.Create();
-            this.queue.Enqueue(waitCoroutineLock);
+            self.queue.Enqueue(waitCoroutineLock);
             if (time > 0)
             {
-                TimerComponent timerComponent = this.coroutineLockComponent.TimerComponent;
-                long tillTime = timerComponent.TimeInfo.ClientFrameTime() + time;
-                timerComponent.NewOnceTimer(tillTime, TimerCoreInvokeType.CoroutineTimeout, waitCoroutineLock);
+                long tillTime = self.Fiber().TimeInfo.ClientFrameTime() + time;
+                self.Root().GetComponent<TimerComponent>().NewOnceTimer(tillTime, TimerCoreInvokeType.CoroutineTimeout, waitCoroutineLock);
             }
-            this.currentCoroutineLock = await waitCoroutineLock.Wait();
-            return this.currentCoroutineLock;
+            self.CurrentCoroutineLock = await waitCoroutineLock.Wait();
+            return self.CurrentCoroutineLock;
         }
 
-        public void Notify(int level)
+        public static void Notify(this CoroutineLockQueue self, int level)
         {
             // 有可能WaitCoroutineLock已经超时抛出异常,所以要找到一个未处理的WaitCoroutineLock
-            while (this.queue.Count > 0)
+            while (self.queue.Count > 0)
             {
-                WaitCoroutineLock waitCoroutineLock = queue.Dequeue();
+                WaitCoroutineLock waitCoroutineLock = self.queue.Dequeue();
 
                 if (waitCoroutineLock.IsDisposed())
                 {
                     continue;
                 }
 
-                CoroutineLock coroutineLock = CoroutineLock.Create(this.coroutineLockComponent, type, key, level);
+                CoroutineLock coroutineLock = self.AddChild<CoroutineLock, int, long, int>(self.type, self.Id, level, true);
 
                 waitCoroutineLock.SetResult(coroutineLock);
                 break;
             }
         }
-        
-        public bool IsDisposed
+    }
+    
+    [ChildOf(typeof(CoroutineLockQueueType))]
+    public class CoroutineLockQueue: Entity, IAwake<int>, IDestroy
+    {
+        public int type;
+
+        private EntityRef<CoroutineLock> currentCoroutineLock;
+
+        public CoroutineLock CurrentCoroutineLock
         {
             get
             {
-                return this.coroutineLockComponent == null;
+                return this.currentCoroutineLock;
+            }
+            set
+            {
+                this.currentCoroutineLock = value;
             }
         }
+        
+        public Queue<WaitCoroutineLock> queue = new();
 
-        public void Dispose()
+        public int Count
         {
-            if (this.IsDisposed)
+            get
             {
-                return;
+                return this.queue.Count;
             }
-            
-            this.queue.Clear();
-            this.key = 0;
-            this.type = 0;
-            this.currentCoroutineLock = null;
-            this.coroutineLockComponent = null;
-            ObjectPool.Instance.Recycle(this);
         }
     }
 }

+ 22 - 29
Unity/Assets/Scripts/Core/Fiber/Module/CoroutineLock/CoroutineLockQueueType.cs

@@ -1,52 +1,40 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 
 namespace ET
 {
-    public class CoroutineLockQueueType
+    [FriendOf(typeof(CoroutineLockQueueType))]
+    public static partial class CoroutineLockQueueTypeSystem
     {
-        private readonly CoroutineLockComponent coroutineLockComponent;
-        
-        private readonly int type;
-        
-        private readonly Dictionary<long, CoroutineLockQueue> coroutineLockQueues = new();
-
-        public CoroutineLockQueueType(CoroutineLockComponent coroutineLockComponent, int type)
+        [EntitySystem]
+        private static void Awake(this CoroutineLockQueueType self)
         {
-            this.coroutineLockComponent = coroutineLockComponent;
-            this.type = type;
         }
-
-        private CoroutineLockQueue Get(long key)
+        
+        public static CoroutineLockQueue Get(this CoroutineLockQueueType self, long key)
         {
-            this.coroutineLockQueues.TryGetValue(key, out CoroutineLockQueue queue);
-            return queue;
+            return self.GetChild<CoroutineLockQueue>(key);
         }
 
-        private CoroutineLockQueue New(long key)
+        public static CoroutineLockQueue New(this CoroutineLockQueueType self, long key)
         {
-            CoroutineLockQueue queue = CoroutineLockQueue.Create(this.coroutineLockComponent, this.type, key);
-            this.coroutineLockQueues.Add(key, queue);
+            CoroutineLockQueue queue = self.AddChildWithId<CoroutineLockQueue, int>(key, (int)self.Id, true);
             return queue;
         }
 
-        private void Remove(long key)
+        public static void Remove(this CoroutineLockQueueType self, long key)
         {
-            if (this.coroutineLockQueues.Remove(key, out CoroutineLockQueue queue))
-            {
-                queue.Dispose();
-            }
+            self.RemoveChild(key);
         }
 
-        public async ETTask<CoroutineLock> Wait(long key, int time)
+        public static async ETTask<CoroutineLock> Wait(this CoroutineLockQueueType self, long key, int time)
         {
-            CoroutineLockQueue queue = this.Get(key) ?? this.New(key);
+            CoroutineLockQueue queue = self.Get(key) ?? self.New(key);
             return await queue.Wait(time);
         }
 
-        public void Notify(long key, int level)
+        public static void Notify(this CoroutineLockQueueType self, long key, int level)
         {
-            CoroutineLockQueue queue = this.Get(key);
+            CoroutineLockQueue queue = self.Get(key);
             if (queue == null)
             {
                 return;
@@ -54,10 +42,15 @@ namespace ET
             
             if (queue.Count == 0)
             {
-                this.Remove(key);
+                self.Remove(key);
             }
 
             queue.Notify(level);
         }
     }
+    
+    [ChildOf(typeof(CoroutineLockComponent))]
+    public class CoroutineLockQueueType: Entity, IAwake
+    {
+    }
 }

+ 92 - 90
Unity/Assets/Scripts/Core/Fiber/Module/Timer/TimerComponent.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 
 namespace ET
 {
@@ -54,57 +53,30 @@ namespace ET
         public object Args;
     }
 
-    public class TimerComponent
+    public static partial class TimerComponentSystem
     {
-        private bool IsDisposed;
-        
-        public readonly TimeInfo TimeInfo;
-        /// <summary>
-        /// key: time, value: timer id
-        /// </summary>
-        private readonly MultiMap<long, long> TimeId = new(1000);
-
-        private readonly Queue<long> timeOutTime = new();
-
-        private readonly Queue<long> timeOutTimerIds = new();
-
-        private readonly Dictionary<long, TimerAction> timerActions = new();
-
-        private long idGenerator;
-
-        // 记录最小时间,不用每次都去MultiMap取第一个值
-        private long minTime = long.MaxValue;
-
-        public TimerComponent(TimeInfo timeInfo)
+        [EntitySystem]
+        private static void Awake(this TimerComponent self)
         {
-            this.TimeInfo = timeInfo;
+            self.Fiber().TimerComponent = self;
         }
-
-        private long GetId()
-        {
-            return ++this.idGenerator;
-        }
-
-        private long GetNow()
-        {
-            return this.TimeInfo.ClientFrameTime();
-        }
-
-        public void Update()
+        
+        [EntitySystem]
+        private static void Update(this TimerComponent self)
         {
-            if (this.TimeId.Count == 0)
+            if (self.timeId.Count == 0)
             {
                 return;
             }
 
-            long timeNow = GetNow();
+            long timeNow = self.GetNow();
 
-            if (timeNow < this.minTime)
+            if (timeNow < self.minTime)
             {
                 return;
             }
 
-            using (var enumerator = this.TimeId.GetEnumerator())
+            using (var enumerator = self.timeId.GetEnumerator())
             {
                 while (enumerator.MoveNext())
                 {
@@ -112,45 +84,55 @@ namespace ET
                     long k = kv.Key;
                     if (k > timeNow)
                     {
-                        this.minTime = k;
+                        self.minTime = k;
                         break;
                     }
 
-                    this.timeOutTime.Enqueue(k);
+                    self.timeOutTime.Enqueue(k);
                 }
             }
 
-            while (this.timeOutTime.Count > 0)
+            while (self.timeOutTime.Count > 0)
             {
-                long time = this.timeOutTime.Dequeue();
-                var list = this.TimeId[time];
+                long time = self.timeOutTime.Dequeue();
+                var list = self.timeId[time];
                 for (int i = 0; i < list.Count; ++i)
                 {
                     long timerId = list[i];
-                    this.timeOutTimerIds.Enqueue(timerId);
+                    self.timeOutTimerIds.Enqueue(timerId);
                 }
-                this.TimeId.Remove(time);
+                self.timeId.Remove(time);
             }
 
-            if (this.TimeId.Count == 0)
+            if (self.timeId.Count == 0)
             {
-                this.minTime = long.MaxValue;
+                self.minTime = long.MaxValue;
             }
 
-            while (this.timeOutTimerIds.Count > 0)
+            while (self.timeOutTimerIds.Count > 0)
             {
-                long timerId = this.timeOutTimerIds.Dequeue();
+                long timerId = self.timeOutTimerIds.Dequeue();
 
-                if (!this.timerActions.Remove(timerId, out TimerAction timerAction))
+                if (!self.timerActions.Remove(timerId, out TimerAction timerAction))
                 {
                     continue;
                 }
                 
-                this.Run(timerAction);
+                self.Run(timerAction);
             }
         }
+        
+        private static long GetId(this TimerComponent self)
+        {
+            return ++self.idGenerator;
+        }
 
-        private void Run(TimerAction timerAction)
+        private static long GetNow(this TimerComponent self)
+        {
+            return self.Fiber().TimeInfo.ClientFrameTime();
+        }
+
+        private static void Run(this TimerComponent self, TimerAction timerAction)
         {
             switch (timerAction.TimerClass)
             {
@@ -169,41 +151,41 @@ namespace ET
                 }
                 case TimerClass.RepeatedTimer:
                 {                    
-                    long timeNow = GetNow();
+                    long timeNow = self.GetNow();
                     timerAction.StartTime = timeNow;
-                    this.AddTimer(timerAction);
+                    self.AddTimer(timerAction);
                     EventSystem.Instance.Invoke(timerAction.Type, new TimerCallback() { Args = timerAction.Object });
                     break;
                 }
             }
         }
 
-        private void AddTimer(TimerAction timer)
+        private static void AddTimer(this TimerComponent self, TimerAction timer)
         {
             long tillTime = timer.StartTime + timer.Time;
-            this.TimeId.Add(tillTime, timer.Id);
-            this.timerActions.Add(timer.Id, timer);
-            if (tillTime < this.minTime)
+            self.timeId.Add(tillTime, timer.Id);
+            self.timerActions.Add(timer.Id, timer);
+            if (tillTime < self.minTime)
             {
-                this.minTime = tillTime;
+                self.minTime = tillTime;
             }
         }
 
-        public bool Remove(ref long id)
+        public static bool Remove(this TimerComponent self, ref long id)
         {
             long i = id;
             id = 0;
-            return this.Remove(i);
+            return self.Remove(i);
         }
 
-        private bool Remove(long id)
+        private static bool Remove(this TimerComponent self, long id)
         {
             if (id == 0)
             {
                 return false;
             }
 
-            if (!this.timerActions.Remove(id, out TimerAction timerAction))
+            if (!self.timerActions.Remove(id, out TimerAction timerAction))
             {
                 return false;
             }
@@ -211,22 +193,22 @@ namespace ET
             return true;
         }
 
-        public async ETTask WaitTillAsync(long tillTime, ETCancellationToken cancellationToken = null)
+        public static async ETTask WaitTillAsync(this TimerComponent self, long tillTime, ETCancellationToken cancellationToken = null)
         {
-            long timeNow = GetNow();
+            long timeNow = self.GetNow();
             if (timeNow >= tillTime)
             {
                 return;
             }
 
             ETTask tcs = ETTask.Create(true);
-            TimerAction timer = TimerAction.Create(this.GetId(), TimerClass.OnceWaitTimer, timeNow, tillTime - timeNow, 0, tcs);
-            this.AddTimer(timer);
+            TimerAction timer = TimerAction.Create(self.GetId(), TimerClass.OnceWaitTimer, timeNow, tillTime - timeNow, 0, tcs);
+            self.AddTimer(timer);
             long timerId = timer.Id;
 
             void CancelAction()
             {
-                if (this.Remove(timerId))
+                if (self.Remove(timerId))
                 {
                     tcs.SetResult();
                 }
@@ -243,28 +225,28 @@ namespace ET
             }
         }
 
-        public async ETTask WaitFrameAsync(ETCancellationToken cancellationToken = null)
+        public static async ETTask WaitFrameAsync(this TimerComponent self, ETCancellationToken cancellationToken = null)
         {
-            await this.WaitAsync(1, cancellationToken);
+            await self.WaitAsync(1, cancellationToken);
         }
 
-        public async ETTask WaitAsync(long time, ETCancellationToken cancellationToken = null)
+        public static async ETTask WaitAsync(this TimerComponent self, long time, ETCancellationToken cancellationToken = null)
         {
             if (time == 0)
             {
                 return;
             }
 
-            long timeNow = GetNow();
+            long timeNow = self.GetNow();
 
             ETTask tcs = ETTask.Create(true);
-            TimerAction timer = TimerAction.Create(this.GetId(), TimerClass.OnceWaitTimer, timeNow, time, 0, tcs);
-            this.AddTimer(timer);
+            TimerAction timer = TimerAction.Create(self.GetId(), TimerClass.OnceWaitTimer, timeNow, time, 0, tcs);
+            self.AddTimer(timer);
             long timerId = timer.Id;
 
             void CancelAction()
             {
-                if (this.Remove(timerId))
+                if (self.Remove(timerId))
                 {
                     tcs.SetResult();
                 }
@@ -284,32 +266,32 @@ namespace ET
         // 用这个优点是可以热更,缺点是回调式的写法,逻辑不连贯。WaitTillAsync不能热更,优点是逻辑连贯。
         // wait时间短并且逻辑需要连贯的建议WaitTillAsync
         // wait时间长不需要逻辑连贯的建议用NewOnceTimer
-        public long NewOnceTimer(long tillTime, int type, object args)
+        public static long NewOnceTimer(this TimerComponent self, long tillTime, int type, object args)
         {
-            long timeNow = GetNow();
+            long timeNow = self.GetNow();
             if (tillTime < timeNow)
             {
                 Log.Error($"new once time too small: {tillTime}");
             }
 
-            TimerAction timer = TimerAction.Create(this.GetId(), TimerClass.OnceTimer, timeNow, tillTime - timeNow, type, args);
-            this.AddTimer(timer);
+            TimerAction timer = TimerAction.Create(self.GetId(), TimerClass.OnceTimer, timeNow, tillTime - timeNow, type, args);
+            self.AddTimer(timer);
             return timer.Id;
         }
 
-        public long NewFrameTimer(int type, object args)
+        public static long NewFrameTimer(this TimerComponent self, int type, object args)
         {
 #if DOTNET
-            return this.NewRepeatedTimerInner(100, type, args);
+            return self.NewRepeatedTimerInner(100, type, args);
 #else
-            return this.NewRepeatedTimerInner(0, type, args);
+            return self.NewRepeatedTimerInner(0, type, args);
 #endif
         }
 
         /// <summary>
         /// 创建一个RepeatedTimer
         /// </summary>
-        private long NewRepeatedTimerInner(long time, int type, object args)
+        private static long NewRepeatedTimerInner(this TimerComponent self, long time, int type, object args)
         {
 #if DOTNET
             if (time < 100)
@@ -318,15 +300,15 @@ namespace ET
             }
 #endif
             
-            long timeNow = GetNow();
-            TimerAction timer = TimerAction.Create(this.GetId(), TimerClass.RepeatedTimer, timeNow, time, type, args);
+            long timeNow = self.GetNow();
+            TimerAction timer = TimerAction.Create(self.GetId(), TimerClass.RepeatedTimer, timeNow, time, type, args);
 
             // 每帧执行的不用加到timerId中,防止遍历
-            this.AddTimer(timer);
+            self.AddTimer(timer);
             return timer.Id;
         }
 
-        public long NewRepeatedTimer(long time, int type, object args)
+        public static long NewRepeatedTimer(this TimerComponent self, long time, int type, object args)
         {
             if (time < 100)
             {
@@ -334,7 +316,27 @@ namespace ET
                 return 0;
             }
 
-            return this.NewRepeatedTimerInner(time, type, args);
+            return self.NewRepeatedTimerInner(time, type, args);
         }
     }
+
+    [ComponentOf(typeof(Scene))]
+    public class TimerComponent: Entity, IAwake, IUpdate
+    {
+        /// <summary>
+        /// key: time, value: timer id
+        /// </summary>
+        public readonly MultiMap<long, long> timeId = new(1000);
+
+        public readonly Queue<long> timeOutTime = new();
+
+        public readonly Queue<long> timeOutTimerIds = new();
+
+        public readonly Dictionary<long, TimerAction> timerActions = new();
+
+        public long idGenerator;
+
+        // 记录最小时间,不用每次都去MultiMap取第一个值
+        public long minTime = long.MaxValue;
+    }
 }

+ 2 - 0
Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/FiberInit_NetClient.cs

@@ -7,6 +7,8 @@
         {
             Scene root = fiberInit.Fiber.Root;
             root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
+            root.AddComponent<TimerComponent>();
+            root.AddComponent<CoroutineLockComponent>();
             root.AddComponent<ActorInnerComponent>();
             root.AddComponent<ActorRecverComponent>();
             await ETTask.CompletedTask;

+ 2 - 0
Unity/Assets/Scripts/Hotfix/Server/Demo/Gate/FiberInit_Gate.cs

@@ -9,6 +9,8 @@ namespace ET.Server
         {
             Scene root = fiberInit.Fiber.Root;
             root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
+            root.AddComponent<TimerComponent>();
+            root.AddComponent<CoroutineLockComponent>();
             root.AddComponent<ActorInnerComponent>();
             root.AddComponent<ActorSenderComponent>();
             root.AddComponent<ActorRecverComponent>();

+ 2 - 0
Unity/Assets/Scripts/Hotfix/Server/Demo/Realm/FiberInit_Realm.cs

@@ -9,6 +9,8 @@ namespace ET.Server
         {
             Scene root = fiberInit.Fiber.Root;
             root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
+            root.AddComponent<TimerComponent>();
+            root.AddComponent<CoroutineLockComponent>();
             root.AddComponent<ActorInnerComponent>();
             root.AddComponent<ActorSenderComponent>();
             root.AddComponent<ActorRecverComponent>();

+ 2 - 0
Unity/Assets/Scripts/Hotfix/Server/LockStep/Map/FiberInit_Map.cs

@@ -9,6 +9,8 @@ namespace ET.Server
         {
             Scene root = fiberInit.Fiber.Root;
             root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
+            root.AddComponent<TimerComponent>();
+            root.AddComponent<CoroutineLockComponent>();
             root.AddComponent<ActorInnerComponent>();
             root.AddComponent<ActorSenderComponent>();
             root.AddComponent<ActorRecverComponent>();

+ 2 - 0
Unity/Assets/Scripts/Hotfix/Server/LockStep/Match/FiberInit_Match.cs

@@ -9,6 +9,8 @@ namespace ET.Server
         {
             Scene root = fiberInit.Fiber.Root;
             root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
+            root.AddComponent<TimerComponent>();
+            root.AddComponent<CoroutineLockComponent>();
             root.AddComponent<ActorInnerComponent>();
             root.AddComponent<ActorSenderComponent>();
             root.AddComponent<ActorRecverComponent>();

+ 2 - 0
Unity/Assets/Scripts/Hotfix/Server/LockStep/Room/FiberInit_RoomRoot.cs

@@ -9,6 +9,8 @@ namespace ET.Server
         {
             Scene root = fiberInit.Fiber.Root;
             root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
+            root.AddComponent<TimerComponent>();
+            root.AddComponent<CoroutineLockComponent>();
             root.AddComponent<ActorInnerComponent>();
             root.AddComponent<ActorSenderComponent>();
             root.AddComponent<ActorRecverComponent>();

+ 2 - 0
Unity/Assets/Scripts/Hotfix/Server/Module/ActorLocation/FiberInit_Location.cs

@@ -9,6 +9,8 @@ namespace ET.Server
         {
             Scene root = fiberInit.Fiber.Root;
             root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
+            root.AddComponent<TimerComponent>();
+            root.AddComponent<CoroutineLockComponent>();
             root.AddComponent<ActorInnerComponent>();
             root.AddComponent<ActorSenderComponent>();
             root.AddComponent<ActorRecverComponent>();

+ 2 - 1
Unity/Assets/Scripts/Hotfix/Server/Module/NetInner/FiberInit_NetInner.cs

@@ -9,7 +9,8 @@ namespace ET.Server
         {
             Scene root = fiberInit.Fiber.Root;
             root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
-            
+            root.AddComponent<TimerComponent>();
+            root.AddComponent<CoroutineLockComponent>();
             StartSceneConfig startSceneConfig = StartSceneConfigCategory.Instance.Get(fiberInit.Fiber.Id);
             root.AddComponent<NetProcessComponent, IPEndPoint>(startSceneConfig.InnerIPPort);
             root.AddComponent<ActorOuterComponent>();

+ 3 - 0
Unity/Assets/Scripts/HotfixView/Client/Demo/EntryEvent3_InitClient.cs

@@ -10,6 +10,9 @@ namespace ET.Client
         {
             World.Instance.AddSingleton<UIEventComponent>();
             
+            root.AddComponent<TimerComponent>();
+            root.AddComponent<CoroutineLockComponent>();
+            
             GlobalComponent globalComponent = root.AddComponent<GlobalComponent>();
             root.AddComponent<UIGlobalComponent>();
             root.AddComponent<UIComponent>();