Ver código fonte

NetClient跟NetServer合并为NetOuterComponent,使用Invoker分发OnRead的消息,这样做的原因是可能很多地方会用到这个组件,大部分逻辑一样,只是不同的Scene收到消息处理不一样,所以用SceneType做分发即可

tanghai 2 anos atrás
pai
commit
97f1781b4d
27 arquivos alterados com 1362 adições e 239 exclusões
  1. 1 0
      Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/FiberInit_NetClient.cs
  2. 2 1
      Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/Main2NetClient_LoginHandler.cs
  3. 1 1
      Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/Router/RouterHelper.cs
  4. 0 107
      Unity/Assets/Scripts/Hotfix/Client/Module/Message/NetClientComponentSystem.cs
  5. 40 0
      Unity/Assets/Scripts/Hotfix/Client/Module/Message/NetOuterComponentOnReadInvoker_NetClient.cs
  6. 1 1
      Unity/Assets/Scripts/Hotfix/Client/Module/Message/NetOuterComponentOnReadInvoker_NetClient.cs.meta
  7. 2 2
      Unity/Assets/Scripts/Hotfix/Server/Benchmark/BenchmarkClientComponentSystem.cs
  8. 1 1
      Unity/Assets/Scripts/Hotfix/Server/Benchmark/FiberInit_BenchmarkClient.cs
  9. 1 1
      Unity/Assets/Scripts/Hotfix/Server/Benchmark/FiberInit_BenchmarkServer.cs
  10. 27 0
      Unity/Assets/Scripts/Hotfix/Server/Benchmark/NetOuterComponentOnReadInvoker_BenchmarkServer.cs
  11. 1 1
      Unity/Assets/Scripts/Hotfix/Server/Demo/Gate/FiberInit_Gate.cs
  12. 10 9
      Unity/Assets/Scripts/Hotfix/Server/Demo/Gate/NetOuterComponentOnReadInvoker_Gate.cs
  13. 1 1
      Unity/Assets/Scripts/Hotfix/Server/Demo/Gate/NetOuterComponentOnReadInvoker_Gate.cs.meta
  14. 1 1
      Unity/Assets/Scripts/Hotfix/Server/Demo/Realm/FiberInit_Realm.cs
  15. 27 0
      Unity/Assets/Scripts/Hotfix/Server/Demo/Realm/NetOuterComponentOnReadInvoker_Realm.cs
  16. 1 1
      Unity/Assets/Scripts/Hotfix/Server/Demo/Realm/NetOuterComponentOnReadInvoker_Realm.cs.meta
  17. 0 72
      Unity/Assets/Scripts/Hotfix/Server/Module/Message/NetServerComponentSystem.cs
  18. 107 0
      Unity/Assets/Scripts/Hotfix/Share/Module/Message/NetOuterComponentSystem.cs
  19. 1 1
      Unity/Assets/Scripts/Hotfix/Share/Module/Message/NetOuterComponentSystem.cs.meta
  20. 0 12
      Unity/Assets/Scripts/Model/Client/Module/Message/NetClientComponent.cs
  21. 0 16
      Unity/Assets/Scripts/Model/Server/Module/Message/NetServerComponent.cs
  22. 0 11
      Unity/Assets/Scripts/Model/Server/Module/Message/NetServerComponent.cs.meta
  23. 17 0
      Unity/Assets/Scripts/Model/Share/Module/Message/NetOuterComponent.cs
  24. 11 0
      Unity/Assets/Scripts/Model/Share/Module/Message/NetOuterComponent.cs.meta
  25. 8 0
      Unity/Assets/Scripts/Model/Share/Module/Scene/FiberParentComponent.cs
  26. 11 0
      Unity/Assets/Scripts/Model/Share/Module/Scene/FiberParentComponent.cs.meta
  27. 1090 0
      WebGL/UserSettings/Layouts/default-2021.dwlt

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

@@ -10,6 +10,7 @@
             root.AddComponent<TimerComponent>();
             root.AddComponent<CoroutineLockComponent>();
             root.AddComponent<MessageInnerSender>();
+            root.AddComponent<FiberParentComponent>();
             await ETTask.CompletedTask;
         }
     }

+ 2 - 1
Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/Main2NetClient_LoginHandler.cs

@@ -19,7 +19,8 @@ namespace ET.Client
                 routerAddressComponent =
                         root.AddComponent<RouterAddressComponent, string, int>(ConstValue.RouterHttpHost, ConstValue.RouterHttpPort);
                 await routerAddressComponent.Init();
-                root.AddComponent<NetClientComponent, AddressFamily, int>(routerAddressComponent.RouterManagerIPAddress.AddressFamily, request.OwnerFiberId);
+                root.AddComponent<NetOuterComponent, AddressFamily>(routerAddressComponent.RouterManagerIPAddress.AddressFamily);
+                root.GetComponent<FiberParentComponent>().ParentFiberId = request.OwnerFiberId;
             }
             IPEndPoint realmAddress = routerAddressComponent.GetRealmAddress(account);
 

+ 1 - 1
Unity/Assets/Scripts/Hotfix/Client/Demo/NetClient/Router/RouterHelper.cs

@@ -18,7 +18,7 @@ namespace ET.Client
             
             root.Fiber().Info($"get router: {recvLocalConn} {routerAddress}");
 
-            Session routerSession = root.GetComponent<NetClientComponent>().Create(routerAddress, address, recvLocalConn);
+            Session routerSession = root.GetComponent<NetOuterComponent>().Create(routerAddress, address, recvLocalConn);
             routerSession.AddComponent<PingComponent>();
             routerSession.AddComponent<RouterCheckComponent>();
             

+ 0 - 107
Unity/Assets/Scripts/Hotfix/Client/Module/Message/NetClientComponentSystem.cs

@@ -1,107 +0,0 @@
-using System;
-using System.Net;
-using System.Net.Sockets;
-using MongoDB.Bson;
-
-namespace ET.Client
-{
-    [EntitySystemOf(typeof(NetClientComponent))]
-    [FriendOf(typeof(NetClientComponent))]
-    public static partial class NetClientComponentSystem
-    {
-        [EntitySystem]
-        private static void Awake(this NetClientComponent self, AddressFamily addressFamily, int ownerFiberId)
-        {
-            self.AService = new KService(addressFamily, ServiceType.Outer, self.Fiber().Log);
-            self.AService.ReadCallback = self.OnRead;
-            self.AService.ErrorCallback = self.OnError;
-            self.OwnerFiberId = ownerFiberId;
-        }
-
-        [EntitySystem]
-        private static void Destroy(this NetClientComponent self)
-        {
-            self.AService.Dispose();
-        }
-
-        [EntitySystem]
-        private static void Update(this NetClientComponent self)
-        {
-            self.AService.Update();
-        }
-
-        private static void OnRead(this NetClientComponent self, long channelId, ActorId actorId, object message)
-        {
-            Session session = self.GetChild<Session>(channelId);
-            if (session == null)
-            {
-                return;
-            }
-
-            session.LastRecvTime = TimeInfo.Instance.ClientNow();
-
-            switch (message)
-            {
-                case IResponse response:
-                    {
-                        session.OnResponse(response);
-                        break;
-                    }
-                case ISessionMessage:
-                    {
-                        MessageSessionDispatcher.Instance.Handle(session, message);
-                        break;
-                    }
-                case IMessage iActorMessage:
-                    {
-                        // 扔到Main纤程队列中
-                        self.Fiber().MessageInnerSender.Send(new ActorId(self.Fiber().Process, self.OwnerFiberId), iActorMessage);
-                        break;
-                    }
-                default:
-                    {
-                        throw new Exception($"not found handler: {message}");
-                    }
-            }
-        }
-
-        private static void OnError(this NetClientComponent self, long channelId, int error)
-        {
-            Session session = self.GetChild<Session>(channelId);
-            if (session == null)
-            {
-                return;
-            }
-
-            session.Error = error;
-            session.Dispose();
-        }
-
-        public static Session Create(this NetClientComponent self, IPEndPoint realIPEndPoint)
-        {
-            long channelId = NetServices.Instance.CreateConnectChannelId();
-            Session session = self.AddChildWithId<Session, AService>(channelId, self.AService);
-            session.RemoteAddress = realIPEndPoint;
-            if (self.IScene.SceneType != SceneType.BenchmarkClient)
-            {
-                session.AddComponent<SessionIdleCheckerComponent>();
-            }
-            self.AService.Create(session.Id, realIPEndPoint);
-
-            return session;
-        }
-
-        public static Session Create(this NetClientComponent self, IPEndPoint routerIPEndPoint, IPEndPoint realIPEndPoint, uint localConn)
-        {
-            long channelId = localConn;
-            Session session = self.AddChildWithId<Session, AService>(channelId, self.AService);
-            session.RemoteAddress = realIPEndPoint;
-            if (self.IScene.SceneType != SceneType.BenchmarkClient)
-            {
-                session.AddComponent<SessionIdleCheckerComponent>();
-            }
-            self.AService.Create(session.Id, routerIPEndPoint);
-            return session;
-        }
-    }
-}

+ 40 - 0
Unity/Assets/Scripts/Hotfix/Client/Module/Message/NetOuterComponentOnReadInvoker_NetClient.cs

@@ -0,0 +1,40 @@
+using System;
+
+namespace ET.Client
+{
+    [Invoke((long)SceneType.NetClient)]
+    public class NetOuterComponentOnReadInvoker_NetClient: AInvokeHandler<NetOuterComponentOnRead>
+    {
+        public override void Handle(NetOuterComponentOnRead args)
+        {
+            Session session = args.Session;
+            object message = args.Message;
+            Fiber fiber = session.Fiber();
+            // 根据消息接口判断是不是Actor消息,不同的接口做不同的处理,比如需要转发给Chat Scene,可以做一个IChatMessage接口
+            switch (message)
+            {
+                case IResponse response:
+                {
+                    session.OnResponse(response);
+                    break;
+                }
+                case ISessionMessage:
+                {
+                    MessageSessionDispatcher.Instance.Handle(session, message);
+                    break;
+                }
+                case IMessage iActorMessage:
+                {
+                    // 扔到Main纤程队列中
+                    int parentFiberId = fiber.Root.GetComponent<FiberParentComponent>().ParentFiberId;
+                    fiber.MessageInnerSender.Send(new ActorId(fiber.Process, parentFiberId), iActorMessage);
+                    break;
+                }
+                default:
+                {
+                    throw new Exception($"not found handler: {message}");
+                }
+            }
+        }
+    }
+}

+ 1 - 1
Unity/Assets/Scripts/Hotfix/Server/Module/Message/NetServerComponentSystem.cs.meta → Unity/Assets/Scripts/Hotfix/Client/Module/Message/NetOuterComponentOnReadInvoker_NetClient.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 40d0bddfefa8ce34a8349977968fc0cd
+guid: a717e8152c0929841b5a0ba8f74162bb
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

+ 2 - 2
Unity/Assets/Scripts/Hotfix/Server/Benchmark/BenchmarkClientComponentSystem.cs

@@ -18,8 +18,8 @@ namespace ET.Server
 
         private static async ETTask Start(this BenchmarkClientComponent self)
         {
-            NetClientComponent netClientComponent = self.Root().GetComponent<NetClientComponent>();
-            using Session session = netClientComponent.Create(StartSceneConfigCategory.Instance.Benchmark.OuterIPPort);
+            NetOuterComponent netOuterClientComponent = self.Root().GetComponent<NetOuterComponent>();
+            using Session session = netOuterClientComponent.Create(StartSceneConfigCategory.Instance.Benchmark.OuterIPPort);
             List<ETTask> list = new List<ETTask>(100000);
 
             async ETTask Call(Session s)

+ 1 - 1
Unity/Assets/Scripts/Hotfix/Server/Benchmark/FiberInit_BenchmarkClient.cs

@@ -19,7 +19,7 @@ namespace ET.Server
             //root.AddComponent<GateSessionKeyComponent>();
             //root.AddComponent<LocationProxyComponent>();
             //root.AddComponent<ActorLocationSenderComponent>();
-            root.AddComponent<NetClientComponent, AddressFamily, int>(AddressFamily.InterNetwork, ConstFiberId.Main);
+            root.AddComponent<NetOuterComponent, AddressFamily>(AddressFamily.InterNetwork);
             root.AddComponent<BenchmarkClientComponent>();
             await ETTask.CompletedTask;
         }

+ 1 - 1
Unity/Assets/Scripts/Hotfix/Server/Benchmark/FiberInit_BenchmarkServer.cs

@@ -19,7 +19,7 @@ namespace ET.Server
             //root.AddComponent<GateSessionKeyComponent>();
             //root.AddComponent<LocationProxyComponent>();
             //root.AddComponent<ActorLocationSenderComponent>();
-            root.AddComponent<NetServerComponent, IPEndPoint>(StartSceneConfigCategory.Instance.Benchmark.OuterIPPort);
+            root.AddComponent<NetOuterComponent, IPEndPoint>(StartSceneConfigCategory.Instance.Benchmark.OuterIPPort);
             root.AddComponent<BenchmarkServerComponent>();
             await ETTask.CompletedTask;
         }

+ 27 - 0
Unity/Assets/Scripts/Hotfix/Server/Benchmark/NetOuterComponentOnReadInvoker_BenchmarkServer.cs

@@ -0,0 +1,27 @@
+using System;
+
+namespace ET.Server
+{
+    [Invoke((long)SceneType.BenchmarkServer)]
+    public class NetOuterComponentOnReadInvoker_BenchmarkServer: AInvokeHandler<NetOuterComponentOnRead>
+    {
+        public override void Handle(NetOuterComponentOnRead args)
+        {
+            Session session = args.Session;
+            object message = args.Message;
+            // 根据消息接口判断是不是Actor消息,不同的接口做不同的处理,比如需要转发给Chat Scene,可以做一个IChatMessage接口
+            switch (message)
+            {
+                case ISessionMessage:
+                {
+                    MessageSessionDispatcher.Instance.Handle(session, message);
+                    break;
+                }
+                default:
+                {
+                    throw new Exception($"not found handler: {message}");
+                }
+            }
+        }
+    }
+}

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

@@ -19,7 +19,7 @@ namespace ET.Server
             root.AddComponent<MessageLocationSenderComponent>();
 
             StartSceneConfig startSceneConfig = StartSceneConfigCategory.Instance.Get((int)root.Id);
-            root.AddComponent<NetServerComponent, IPEndPoint>(startSceneConfig.InnerIPPort);
+            root.AddComponent<NetOuterComponent, IPEndPoint>(startSceneConfig.InnerIPPort);
             await ETTask.CompletedTask;
         }
     }

+ 10 - 9
Unity/Assets/Scripts/Hotfix/Server/Demo/Gate/NetServerComponentOnReadEvent.cs → Unity/Assets/Scripts/Hotfix/Server/Demo/Gate/NetOuterComponentOnReadInvoker_Gate.cs

@@ -2,19 +2,20 @@
 
 namespace ET.Server
 {
-    [Event(SceneType.Realm | SceneType.Gate | SceneType.BenchmarkServer)]
-    public class NetServerComponentOnReadEvent: AEvent<Scene, NetServerComponentOnRead>
+    [Invoke((long)SceneType.Gate)]
+    //[Invoke((long)SceneType.Realm)]
+    public class NetOuterComponentOnReadInvoker_Gate: AInvokeHandler<NetOuterComponentOnRead>
     {
-        protected override async ETTask Run(Scene scene, NetServerComponentOnRead args)
+        public override void Handle(NetOuterComponentOnRead args)
+        {
+            HandleAsync(args).Coroutine();
+        }
+
+        private async ETTask HandleAsync(NetOuterComponentOnRead args)
         {
             Session session = args.Session;
             object message = args.Message;
-            Scene root = scene.Root();
-            if (message is IResponse response)
-            {
-                session.OnResponse(response);
-                return;
-            }
+            Scene root = args.Session.Root();
             // 根据消息接口判断是不是Actor消息,不同的接口做不同的处理,比如需要转发给Chat Scene,可以做一个IChatMessage接口
             switch (message)
             {

+ 1 - 1
Unity/Assets/Scripts/Hotfix/Client/Module/Message/NetClientComponentSystem.cs.meta → Unity/Assets/Scripts/Hotfix/Server/Demo/Gate/NetOuterComponentOnReadInvoker_Gate.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 7fb1278bab55fff4789e94463d9cbdab
+guid: a2baa23740353974ebec1863ff353d72
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

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

@@ -14,7 +14,7 @@ namespace ET.Server
             root.AddComponent<MessageInnerSender>();
             root.AddComponent<MessageSender>();
             StartSceneConfig startSceneConfig = StartSceneConfigCategory.Instance.Get(root.Fiber.Id);
-            root.AddComponent<NetServerComponent, IPEndPoint>(startSceneConfig.InnerIPPort);
+            root.AddComponent<NetOuterComponent, IPEndPoint>(startSceneConfig.InnerIPPort);
 
             await ETTask.CompletedTask;
         }

+ 27 - 0
Unity/Assets/Scripts/Hotfix/Server/Demo/Realm/NetOuterComponentOnReadInvoker_Realm.cs

@@ -0,0 +1,27 @@
+using System;
+
+namespace ET.Server
+{
+    [Invoke((long)SceneType.Realm)]
+    public class NetOuterComponentOnReadInvoker_Realm: AInvokeHandler<NetOuterComponentOnRead>
+    {
+        public override void Handle(NetOuterComponentOnRead args)
+        {
+            Session session = args.Session;
+            object message = args.Message;
+            // 根据消息接口判断是不是Actor消息,不同的接口做不同的处理,比如需要转发给Chat Scene,可以做一个IChatMessage接口
+            switch (message)
+            {
+                case ISessionMessage:
+                {
+                    MessageSessionDispatcher.Instance.Handle(session, message);
+                    break;
+                }
+                default:
+                {
+                    throw new Exception($"not found handler: {message}");
+                }
+            }
+        }
+    }
+}

+ 1 - 1
Unity/Assets/Scripts/Model/Client/Module/Message/NetClientComponent.cs.meta → Unity/Assets/Scripts/Hotfix/Server/Demo/Realm/NetOuterComponentOnReadInvoker_Realm.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: f48eeb5d55c27fc4c8d2babf0d08e471
+guid: 50c06c8dfbc01a348ad36c35d5d51685
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

+ 0 - 72
Unity/Assets/Scripts/Hotfix/Server/Module/Message/NetServerComponentSystem.cs

@@ -1,72 +0,0 @@
-using System.Net;
-using MongoDB.Bson;
-
-namespace ET.Server
-{
-    [EntitySystemOf(typeof(NetServerComponent))]
-    [FriendOf(typeof(NetServerComponent))]
-    public static partial class NetServerComponentSystem
-    {
-        [EntitySystem]
-        private static void Awake(this NetServerComponent self, IPEndPoint address)
-        {
-            self.AService = new KService(address, ServiceType.Outer, self.Fiber().Log);
-            self.AService.AcceptCallback = self.OnAccept;
-            self.AService.ReadCallback = self.OnRead;
-            self.AService.ErrorCallback = self.OnError;
-        }
-        
-        [EntitySystem]
-        private static void Update(this NetServerComponent self)
-        {
-            self.AService.Update();
-        }
-
-        [EntitySystem]
-        private static void Destroy(this NetServerComponent self)
-        {
-            self.AService.Dispose();
-        }
-
-        private static void OnError(this NetServerComponent self, long channelId, int error)
-        {
-            Session session = self.GetChild<Session>(channelId);
-            if (session == null)
-            {
-                return;
-            }
-
-            session.Error = error;
-            session.Dispose();
-        }
-
-        // 这个channelId是由CreateAcceptChannelId生成的
-        private static void OnAccept(this NetServerComponent self, long channelId, IPEndPoint ipEndPoint)
-        {
-            Session session = self.AddChildWithId<Session, AService>(channelId, self.AService);
-            session.RemoteAddress = ipEndPoint;
-
-            if (self.IScene.SceneType != SceneType.BenchmarkServer)
-            {
-                // 挂上这个组件,5秒就会删除session,所以客户端验证完成要删除这个组件。该组件的作用就是防止外挂一直连接不发消息也不进行权限验证
-                session.AddComponent<SessionAcceptTimeoutComponent>();
-                // 客户端连接,2秒检查一次recv消息,10秒没有消息则断开
-                session.AddComponent<SessionIdleCheckerComponent>();
-            }
-        }
-        
-        private static void OnRead(this NetServerComponent self, long channelId, ActorId actorId, object message)
-        {
-            Session session = self.GetChild<Session>(channelId);
-            if (session == null)
-            {
-                return;
-            }
-            session.LastRecvTime = TimeInfo.Instance.ClientNow();
-            
-            LogMsg.Instance.Debug(self.Fiber(), message);
-			
-            EventSystem.Instance.Publish(self.Scene(), new NetServerComponentOnRead() {Session = session, Message = message});
-        }
-    }
-}

+ 107 - 0
Unity/Assets/Scripts/Hotfix/Share/Module/Message/NetOuterComponentSystem.cs

@@ -0,0 +1,107 @@
+using System.Net;
+using System.Net.Sockets;
+
+namespace ET
+{
+    [EntitySystemOf(typeof(NetOuterComponent))]
+    [FriendOf(typeof(NetOuterComponent))]
+    public static partial class NetOuterComponentSystem
+    {
+        [EntitySystem]
+        private static void Awake(this NetOuterComponent self, IPEndPoint address)
+        {
+            self.AService = new KService(address, ServiceType.Outer, self.Fiber().Log);
+            self.AService.AcceptCallback = self.OnAccept;
+            self.AService.ReadCallback = self.OnRead;
+            self.AService.ErrorCallback = self.OnError;
+        }
+        
+        [EntitySystem]
+        private static void Awake(this NetOuterComponent self, AddressFamily addressFamily)
+        {
+            self.AService = new KService(addressFamily, ServiceType.Outer, self.Fiber().Log);
+            self.AService.ReadCallback = self.OnRead;
+            self.AService.ErrorCallback = self.OnError;
+        }
+        
+        [EntitySystem]
+        private static void Update(this NetOuterComponent self)
+        {
+            self.AService.Update();
+        }
+
+        [EntitySystem]
+        private static void Destroy(this NetOuterComponent self)
+        {
+            self.AService.Dispose();
+        }
+
+        private static void OnError(this NetOuterComponent self, long channelId, int error)
+        {
+            Session session = self.GetChild<Session>(channelId);
+            if (session == null)
+            {
+                return;
+            }
+
+            session.Error = error;
+            session.Dispose();
+        }
+
+        // 这个channelId是由CreateAcceptChannelId生成的
+        private static void OnAccept(this NetOuterComponent self, long channelId, IPEndPoint ipEndPoint)
+        {
+            Session session = self.AddChildWithId<Session, AService>(channelId, self.AService);
+            session.RemoteAddress = ipEndPoint;
+
+            if (self.IScene.SceneType != SceneType.BenchmarkServer)
+            {
+                // 挂上这个组件,5秒就会删除session,所以客户端验证完成要删除这个组件。该组件的作用就是防止外挂一直连接不发消息也不进行权限验证
+                session.AddComponent<SessionAcceptTimeoutComponent>();
+                // 客户端连接,2秒检查一次recv消息,10秒没有消息则断开
+                session.AddComponent<SessionIdleCheckerComponent>();
+            }
+        }
+        
+        private static void OnRead(this NetOuterComponent self, long channelId, ActorId actorId, object message)
+        {
+            Session session = self.GetChild<Session>(channelId);
+            if (session == null)
+            {
+                return;
+            }
+            session.LastRecvTime = TimeInfo.Instance.ClientNow();
+            
+            LogMsg.Instance.Debug(self.Fiber(), message);
+            
+            EventSystem.Instance.Invoke((long)self.IScene.SceneType, new NetOuterComponentOnRead() {Session = session, Message = message});
+        }
+        
+        public static Session Create(this NetOuterComponent self, IPEndPoint realIPEndPoint)
+        {
+            long channelId = NetServices.Instance.CreateConnectChannelId();
+            Session session = self.AddChildWithId<Session, AService>(channelId, self.AService);
+            session.RemoteAddress = realIPEndPoint;
+            if (self.IScene.SceneType != SceneType.BenchmarkClient)
+            {
+                session.AddComponent<SessionIdleCheckerComponent>();
+            }
+            self.AService.Create(session.Id, realIPEndPoint);
+
+            return session;
+        }
+
+        public static Session Create(this NetOuterComponent self, IPEndPoint routerIPEndPoint, IPEndPoint realIPEndPoint, uint localConn)
+        {
+            long channelId = localConn;
+            Session session = self.AddChildWithId<Session, AService>(channelId, self.AService);
+            session.RemoteAddress = realIPEndPoint;
+            if (self.IScene.SceneType != SceneType.BenchmarkClient)
+            {
+                session.AddComponent<SessionIdleCheckerComponent>();
+            }
+            self.AService.Create(session.Id, routerIPEndPoint);
+            return session;
+        }
+    }
+}

+ 1 - 1
Unity/Assets/Scripts/Hotfix/Server/Demo/Gate/NetServerComponentOnReadEvent.cs.meta → Unity/Assets/Scripts/Hotfix/Share/Module/Message/NetOuterComponentSystem.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: d8d62222c52da1d43975f204b0d24b07
+guid: 4c0d82cdd1e18474eb59210f801c3fb2
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

+ 0 - 12
Unity/Assets/Scripts/Model/Client/Module/Message/NetClientComponent.cs

@@ -1,12 +0,0 @@
-using System.Net.Sockets;
-
-namespace ET.Client
-{
-    [ComponentOf(typeof(Scene))]
-    public class NetClientComponent: Entity, IAwake<AddressFamily, int>, IDestroy, IUpdate
-    {
-        public AService AService;
-
-        public int OwnerFiberId;
-    }
-}

+ 0 - 16
Unity/Assets/Scripts/Model/Server/Module/Message/NetServerComponent.cs

@@ -1,16 +0,0 @@
-using System.Net;
-
-namespace ET.Server
-{
-    public struct NetServerComponentOnRead
-    {
-        public Session Session;
-        public object Message;
-    }
-    
-    [ComponentOf(typeof(Scene))]
-    public class NetServerComponent: Entity, IAwake<IPEndPoint>, IDestroy, IUpdate
-    {
-        public AService AService;
-    }
-}

+ 0 - 11
Unity/Assets/Scripts/Model/Server/Module/Message/NetServerComponent.cs.meta

@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 6d26c818710bffb459fecf60387869b6
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 

+ 17 - 0
Unity/Assets/Scripts/Model/Share/Module/Message/NetOuterComponent.cs

@@ -0,0 +1,17 @@
+using System.Net;
+using System.Net.Sockets;
+
+namespace ET
+{
+    public struct NetOuterComponentOnRead
+    {
+        public Session Session;
+        public object Message;
+    }
+    
+    [ComponentOf(typeof(Scene))]
+    public class NetOuterComponent: Entity, IAwake<IPEndPoint>, IAwake<AddressFamily>, IDestroy, IUpdate
+    {
+        public AService AService;
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Model/Share/Module/Message/NetOuterComponent.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 601b4bb3c982d5a449b053194f808f47
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Scripts/Model/Share/Module/Scene/FiberParentComponent.cs

@@ -0,0 +1,8 @@
+namespace ET
+{
+    [ComponentOf(typeof(Scene))]
+    public class FiberParentComponent: Entity, IAwake
+    {
+        public int ParentFiberId { get; set; }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Model/Share/Module/Scene/FiberParentComponent.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 72dee30733b618e4faf5b6ba68d06607
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 1090 - 0
WebGL/UserSettings/Layouts/default-2021.dwlt

@@ -0,0 +1,1090 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &1
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12004, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_PixelRect:
+    serializedVersion: 2
+    x: 0
+    y: 42
+    width: 1920
+    height: 990
+  m_ShowMode: 4
+  m_Title: Console
+  m_RootView: {fileID: 10}
+  m_MinSize: {x: 875, y: 371}
+  m_MaxSize: {x: 10000, y: 10000}
+  m_Maximized: 1
+--- !u!114 &2
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: BuildEditor
+  m_EditorClassIdentifier: 
+  m_Children: []
+  m_Position:
+    serializedVersion: 2
+    x: 0
+    y: 627
+    width: 249.5
+    height: 313
+  m_MinSize: {x: 100, y: 100}
+  m_MaxSize: {x: 4000, y: 4000}
+  m_ActualView: {fileID: 15}
+  m_Panes:
+  - {fileID: 15}
+  m_Selected: 0
+  m_LastSelected: 0
+--- !u!114 &3
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Children:
+  - {fileID: 6}
+  - {fileID: 2}
+  m_Position:
+    serializedVersion: 2
+    x: 575
+    y: 0
+    width: 249.5
+    height: 940
+  m_MinSize: {x: 100, y: 200}
+  m_MaxSize: {x: 8096, y: 16192}
+  vertical: 1
+  controlID: 78
+--- !u!114 &4
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: ConsoleWindow
+  m_EditorClassIdentifier: 
+  m_Children: []
+  m_Position:
+    serializedVersion: 2
+    x: 0
+    y: 521
+    width: 1095.5
+    height: 419
+  m_MinSize: {x: 100, y: 100}
+  m_MaxSize: {x: 4000, y: 4000}
+  m_ActualView: {fileID: 21}
+  m_Panes:
+  - {fileID: 21}
+  m_Selected: 0
+  m_LastSelected: 0
+--- !u!114 &5
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Children:
+  - {fileID: 14}
+  - {fileID: 4}
+  m_Position:
+    serializedVersion: 2
+    x: 824.5
+    y: 0
+    width: 1095.5
+    height: 940
+  m_MinSize: {x: 100, y: 200}
+  m_MaxSize: {x: 8096, y: 16192}
+  vertical: 1
+  controlID: 17
+--- !u!114 &6
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: InspectorWindow
+  m_EditorClassIdentifier: 
+  m_Children: []
+  m_Position:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 249.5
+    height: 627
+  m_MinSize: {x: 277, y: 71}
+  m_MaxSize: {x: 4002, y: 4021}
+  m_ActualView: {fileID: 17}
+  m_Panes:
+  - {fileID: 17}
+  m_Selected: 0
+  m_LastSelected: 0
+--- !u!114 &7
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: ProjectBrowser
+  m_EditorClassIdentifier: 
+  m_Children: []
+  m_Position:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 302.5
+    height: 940
+  m_MinSize: {x: 231, y: 271}
+  m_MaxSize: {x: 10001, y: 10021}
+  m_ActualView: {fileID: 16}
+  m_Panes:
+  - {fileID: 16}
+  m_Selected: 0
+  m_LastSelected: 0
+--- !u!114 &8
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Children:
+  - {fileID: 13}
+  m_Position:
+    serializedVersion: 2
+    x: 0
+    y: 30
+    width: 1920
+    height: 940
+  m_MinSize: {x: 400, y: 200}
+  m_MaxSize: {x: 32384, y: 16192}
+  vertical: 0
+  controlID: 15
+--- !u!114 &9
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Children: []
+  m_Position:
+    serializedVersion: 2
+    x: 302.5
+    y: 0
+    width: 272.5
+    height: 940
+  m_MinSize: {x: 202, y: 221}
+  m_MaxSize: {x: 4002, y: 4021}
+  m_ActualView: {fileID: 18}
+  m_Panes:
+  - {fileID: 18}
+  m_Selected: 0
+  m_LastSelected: 0
+--- !u!114 &10
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12008, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Children:
+  - {fileID: 11}
+  - {fileID: 8}
+  - {fileID: 12}
+  m_Position:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 1920
+    height: 990
+  m_MinSize: {x: 875, y: 300}
+  m_MaxSize: {x: 10000, y: 10000}
+  m_UseTopView: 1
+  m_TopViewHeight: 30
+  m_UseBottomView: 1
+  m_BottomViewHeight: 20
+--- !u!114 &11
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12011, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Children: []
+  m_Position:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 1920
+    height: 30
+  m_MinSize: {x: 0, y: 0}
+  m_MaxSize: {x: 0, y: 0}
+  m_LastLoadedLayoutName: 
+--- !u!114 &12
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12042, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Children: []
+  m_Position:
+    serializedVersion: 2
+    x: 0
+    y: 970
+    width: 1920
+    height: 20
+  m_MinSize: {x: 0, y: 0}
+  m_MaxSize: {x: 0, y: 0}
+--- !u!114 &13
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Children:
+  - {fileID: 7}
+  - {fileID: 9}
+  - {fileID: 3}
+  - {fileID: 5}
+  m_Position:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 1920
+    height: 940
+  m_MinSize: {x: 400, y: 200}
+  m_MaxSize: {x: 32384, y: 16192}
+  vertical: 0
+  controlID: 16
+--- !u!114 &14
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: SceneView
+  m_EditorClassIdentifier: 
+  m_Children: []
+  m_Position:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 1095.5
+    height: 521
+  m_MinSize: {x: 201, y: 221}
+  m_MaxSize: {x: 4001, y: 4021}
+  m_ActualView: {fileID: 19}
+  m_Panes:
+  - {fileID: 19}
+  - {fileID: 20}
+  m_Selected: 0
+  m_LastSelected: 1
+--- !u!114 &15
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 52155b8c452647ec8b84033519269054, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_MinSize: {x: 100, y: 100}
+  m_MaxSize: {x: 4000, y: 4000}
+  m_TitleContent:
+    m_Text: BuildEditor
+    m_Image: {fileID: 0}
+    m_Tooltip: 
+  m_Pos:
+    serializedVersion: 2
+    x: 575
+    y: 699
+    width: 247.5
+    height: 292
+  m_ViewDataDictionary: {fileID: 0}
+  m_OverlayCanvas:
+    m_LastAppliedPresetName: Default
+    m_SaveData: []
+    m_OverlaysVisible: 1
+--- !u!114 &16
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12014, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_MinSize: {x: 230, y: 250}
+  m_MaxSize: {x: 10000, y: 10000}
+  m_TitleContent:
+    m_Text: Project
+    m_Image: {fileID: -5179483145760003458, guid: 0000000000000000d000000000000000,
+      type: 0}
+    m_Tooltip: 
+  m_Pos:
+    serializedVersion: 2
+    x: 0
+    y: 72
+    width: 301.5
+    height: 919
+  m_ViewDataDictionary: {fileID: 0}
+  m_OverlayCanvas:
+    m_LastAppliedPresetName: Default
+    m_SaveData: []
+    m_OverlaysVisible: 1
+  m_SearchFilter:
+    m_NameFilter: 
+    m_ClassNames: []
+    m_AssetLabels: []
+    m_AssetBundleNames: []
+    m_ReferencingInstanceIDs: 
+    m_SceneHandles: 
+    m_ShowAllHits: 0
+    m_SkipHidden: 0
+    m_SearchArea: 1
+    m_Folders: []
+    m_Globs: []
+    m_OriginalText: 
+    m_FilterByTypeIntersection: 0
+  m_ViewMode: 0
+  m_StartGridSize: 64
+  m_LastFolders:
+  - Assets
+  m_LastFoldersGridSize: -1
+  m_LastProjectPath: C:\Documents\ET\WebGL
+  m_LockTracker:
+    m_IsLocked: 0
+  m_FolderTreeState:
+    scrollPos: {x: 0, y: 0}
+    m_SelectedIDs: aac10000
+    m_LastClickedID: 49578
+    m_ExpandedIDs: 00000000b06a0000b26a0000b46a0000b66a0000b86a0000ba6a0000bc6a0000
+    m_RenameOverlay:
+      m_UserAcceptedRename: 0
+      m_Name: 
+      m_OriginalName: 
+      m_EditFieldRect:
+        serializedVersion: 2
+        x: 0
+        y: 0
+        width: 0
+        height: 0
+      m_UserData: 0
+      m_IsWaitingForDelay: 0
+      m_IsRenaming: 0
+      m_OriginalEventType: 11
+      m_IsRenamingFilename: 1
+      m_ClientGUIView: {fileID: 0}
+    m_SearchString: 
+    m_CreateAssetUtility:
+      m_EndAction: {fileID: 0}
+      m_InstanceID: 0
+      m_Path: 
+      m_Icon: {fileID: 0}
+      m_ResourceFile: 
+  m_AssetTreeState:
+    scrollPos: {x: 0, y: 0}
+    m_SelectedIDs: 
+    m_LastClickedID: 0
+    m_ExpandedIDs: ffffffff00000000b06a0000b26a0000b46a0000b66a0000b86a0000
+    m_RenameOverlay:
+      m_UserAcceptedRename: 0
+      m_Name: 
+      m_OriginalName: 
+      m_EditFieldRect:
+        serializedVersion: 2
+        x: 0
+        y: 0
+        width: 0
+        height: 0
+      m_UserData: 0
+      m_IsWaitingForDelay: 0
+      m_IsRenaming: 0
+      m_OriginalEventType: 11
+      m_IsRenamingFilename: 1
+      m_ClientGUIView: {fileID: 7}
+    m_SearchString: 
+    m_CreateAssetUtility:
+      m_EndAction: {fileID: 0}
+      m_InstanceID: 0
+      m_Path: 
+      m_Icon: {fileID: 0}
+      m_ResourceFile: 
+  m_ListAreaState:
+    m_SelectedInstanceIDs: 
+    m_LastClickedInstanceID: 0
+    m_HadKeyboardFocusLastEvent: 0
+    m_ExpandedInstanceIDs: c6230000
+    m_RenameOverlay:
+      m_UserAcceptedRename: 0
+      m_Name: 
+      m_OriginalName: 
+      m_EditFieldRect:
+        serializedVersion: 2
+        x: 0
+        y: 0
+        width: 0
+        height: 0
+      m_UserData: 0
+      m_IsWaitingForDelay: 0
+      m_IsRenaming: 0
+      m_OriginalEventType: 11
+      m_IsRenamingFilename: 1
+      m_ClientGUIView: {fileID: 0}
+    m_CreateAssetUtility:
+      m_EndAction: {fileID: 0}
+      m_InstanceID: 0
+      m_Path: 
+      m_Icon: {fileID: 0}
+      m_ResourceFile: 
+    m_NewAssetIndexInList: -1
+    m_ScrollPosition: {x: 0, y: 0}
+    m_GridSize: 64
+  m_SkipHiddenPackages: 0
+  m_DirectoriesAreaWidth: 70
+--- !u!114 &17
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12019, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_MinSize: {x: 275, y: 50}
+  m_MaxSize: {x: 4000, y: 4000}
+  m_TitleContent:
+    m_Text: Inspector
+    m_Image: {fileID: -440750813802333266, guid: 0000000000000000d000000000000000,
+      type: 0}
+    m_Tooltip: 
+  m_Pos:
+    serializedVersion: 2
+    x: 575
+    y: 72
+    width: 247.5
+    height: 606
+  m_ViewDataDictionary: {fileID: 0}
+  m_OverlayCanvas:
+    m_LastAppliedPresetName: Default
+    m_SaveData: []
+    m_OverlaysVisible: 1
+  m_ObjectsLockedBeforeSerialization: []
+  m_InstanceIDsLockedBeforeSerialization: 
+  m_PreviewResizer:
+    m_CachedPref: 160
+    m_ControlHash: -371814159
+    m_PrefName: Preview_InspectorPreview
+  m_LastInspectedObjectInstanceID: -1
+  m_LastVerticalScrollValue: 0
+  m_GlobalObjectId: 
+  m_InspectorMode: 0
+  m_LockTracker:
+    m_IsLocked: 0
+  m_PreviewWindow: {fileID: 0}
+--- !u!114 &18
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12061, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_MinSize: {x: 200, y: 200}
+  m_MaxSize: {x: 4000, y: 4000}
+  m_TitleContent:
+    m_Text: Hierarchy
+    m_Image: {fileID: -3734745235275155857, guid: 0000000000000000d000000000000000,
+      type: 0}
+    m_Tooltip: 
+  m_Pos:
+    serializedVersion: 2
+    x: 302.5
+    y: 72
+    width: 270.5
+    height: 919
+  m_ViewDataDictionary: {fileID: 0}
+  m_OverlayCanvas:
+    m_LastAppliedPresetName: Default
+    m_SaveData: []
+    m_OverlaysVisible: 1
+  m_SceneHierarchy:
+    m_TreeViewState:
+      scrollPos: {x: 0, y: 0}
+      m_SelectedIDs: 
+      m_LastClickedID: 0
+      m_ExpandedIDs: 0293ffffba93ffffcc93ffff2299ffffda99ffffec99ffffde9dffff969effffa89effffe2a3ffff9aa4ffffaca4ffff78a8ffff32a9fffffeaafffff0b3ffffa8b4ffffbab4ffff12b8ffffccb8ffff98baffffc4bfffff7cc0ffff48c2ffff0ec9ffffc4c9ffffd6c9ffffd2ceffff88cfffff9acfffffc2d0ffff78d1ffffa2d1ffff82d2ffff38d3ffffb2d3ffff00d7ffffb6d7ffffc8d7fffff0d8ffffa6d9ffffd0d9ffffb0daffff66dbffffe0dbffff2cdfffffe2dffffff4dffffff0e3ffffa6e4ffffb8e4ffff1ce8ffffd4e8ffffa0eaffff3ef1fffff6f1ffff08f2ffff30f3ffffe6f3ffff10f4fffff0f4ffffa6f5ffffd2f7ffff32fbffff
+      m_RenameOverlay:
+        m_UserAcceptedRename: 0
+        m_Name: 
+        m_OriginalName: 
+        m_EditFieldRect:
+          serializedVersion: 2
+          x: 0
+          y: 0
+          width: 0
+          height: 0
+        m_UserData: 0
+        m_IsWaitingForDelay: 0
+        m_IsRenaming: 0
+        m_OriginalEventType: 11
+        m_IsRenamingFilename: 0
+        m_ClientGUIView: {fileID: 0}
+      m_SearchString: 
+    m_ExpandedScenes: []
+    m_CurrenRootInstanceID: 0
+    m_LockTracker:
+      m_IsLocked: 0
+    m_CurrentSortingName: TransformSorting
+  m_WindowGUID: 4c969a2b90040154d917609493e03593
+--- !u!114 &19
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12013, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_MinSize: {x: 200, y: 200}
+  m_MaxSize: {x: 4000, y: 4000}
+  m_TitleContent:
+    m_Text: Scene
+    m_Image: {fileID: 8634526014445323508, guid: 0000000000000000d000000000000000,
+      type: 0}
+    m_Tooltip: 
+  m_Pos:
+    serializedVersion: 2
+    x: 824.5
+    y: 72
+    width: 1094.5
+    height: 500
+  m_ViewDataDictionary: {fileID: 0}
+  m_OverlayCanvas:
+    m_LastAppliedPresetName: Default
+    m_SaveData:
+    - dockPosition: 0
+      containerId: overlay-toolbar__top
+      floating: 0
+      collapsed: 0
+      displayed: 1
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: -98, y: -26}
+      snapCorner: 3
+      id: Tool Settings
+      index: 0
+      layout: 1
+    - dockPosition: 0
+      containerId: overlay-toolbar__top
+      floating: 0
+      collapsed: 0
+      displayed: 1
+      snapOffset: {x: -141, y: 149}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 1
+      id: unity-grid-and-snap-toolbar
+      index: 1
+      layout: 1
+    - dockPosition: 1
+      containerId: overlay-toolbar__top
+      floating: 0
+      collapsed: 0
+      displayed: 1
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: unity-scene-view-toolbar
+      index: 0
+      layout: 1
+    - dockPosition: 1
+      containerId: overlay-toolbar__top
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 1
+      id: unity-search-toolbar
+      index: 1
+      layout: 1
+    - dockPosition: 0
+      containerId: overlay-container--left
+      floating: 0
+      collapsed: 0
+      displayed: 1
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: unity-transform-toolbar
+      index: 0
+      layout: 2
+    - dockPosition: 0
+      containerId: overlay-container--left
+      floating: 0
+      collapsed: 0
+      displayed: 1
+      snapOffset: {x: 0, y: 197}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: unity-component-tools
+      index: 1
+      layout: 2
+    - dockPosition: 0
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 1
+      snapOffset: {x: 67.5, y: 86}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Orientation
+      index: 0
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Light Settings
+      index: 0
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Camera
+      index: 1
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Cloth Constraints
+      index: 2
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Cloth Collisions
+      index: 3
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Navmesh Display
+      index: 4
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Agent Display
+      index: 5
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Obstacle Display
+      index: 6
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Occlusion Culling
+      index: 7
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Physics Debugger
+      index: 8
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Scene Visibility
+      index: 9
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Particles
+      index: 10
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Tilemap
+      index: 11
+      layout: 4
+    - dockPosition: 1
+      containerId: overlay-container--right
+      floating: 0
+      collapsed: 0
+      displayed: 0
+      snapOffset: {x: 0, y: 0}
+      snapOffsetDelta: {x: 0, y: 0}
+      snapCorner: 0
+      id: Scene View/Tilemap Palette Helper
+      index: 12
+      layout: 4
+    m_OverlaysVisible: 1
+  m_WindowGUID: cc27987af1a868c49b0894db9c0f5429
+  m_Gizmos: 1
+  m_OverrideSceneCullingMask: 6917529027641081856
+  m_SceneIsLit: 1
+  m_SceneLighting: 1
+  m_2DMode: 0
+  m_isRotationLocked: 0
+  m_PlayAudio: 0
+  m_AudioPlay: 0
+  m_Position:
+    m_Target: {x: 0, y: 0, z: 0}
+    speed: 2
+    m_Value: {x: 0, y: 0, z: 0}
+  m_RenderMode: 0
+  m_CameraMode:
+    drawMode: 0
+    name: Shaded
+    section: Shading Mode
+  m_ValidateTrueMetals: 0
+  m_DoValidateTrueMetals: 0
+  m_ExposureSliderValue: 0
+  m_SceneViewState:
+    m_AlwaysRefresh: 0
+    showFog: 1
+    showSkybox: 1
+    showFlares: 1
+    showImageEffects: 1
+    showParticleSystems: 1
+    showVisualEffectGraphs: 1
+    m_FxEnabled: 1
+  m_Grid:
+    xGrid:
+      m_Fade:
+        m_Target: 0
+        speed: 2
+        m_Value: 0
+      m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4}
+      m_Pivot: {x: 0, y: 0, z: 0}
+      m_Size: {x: 0, y: 0}
+    yGrid:
+      m_Fade:
+        m_Target: 1
+        speed: 2
+        m_Value: 1
+      m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4}
+      m_Pivot: {x: 0, y: 0, z: 0}
+      m_Size: {x: 1, y: 1}
+    zGrid:
+      m_Fade:
+        m_Target: 0
+        speed: 2
+        m_Value: 0
+      m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4}
+      m_Pivot: {x: 0, y: 0, z: 0}
+      m_Size: {x: 0, y: 0}
+    m_ShowGrid: 1
+    m_GridAxis: 1
+    m_gridOpacity: 0.5
+  m_Rotation:
+    m_Target: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226}
+    speed: 2
+    m_Value: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226}
+  m_Size:
+    m_Target: 10
+    speed: 2
+    m_Value: 10
+  m_Ortho:
+    m_Target: 0
+    speed: 2
+    m_Value: 0
+  m_CameraSettings:
+    m_Speed: 1
+    m_SpeedNormalized: 0.5
+    m_SpeedMin: 0.001
+    m_SpeedMax: 2
+    m_EasingEnabled: 1
+    m_EasingDuration: 0.4
+    m_AccelerationEnabled: 1
+    m_FieldOfViewHorizontalOrVertical: 60
+    m_NearClip: 0.03
+    m_FarClip: 10000
+    m_DynamicClip: 1
+    m_OcclusionCulling: 0
+  m_LastSceneViewRotation: {x: 0, y: 0, z: 0, w: 0}
+  m_LastSceneViewOrtho: 0
+  m_ReplacementShader: {fileID: 0}
+  m_ReplacementString: 
+  m_SceneVisActive: 1
+  m_LastLockedObject: {fileID: 0}
+  m_ViewIsLockedToObject: 0
+--- !u!114 &20
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12015, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_MinSize: {x: 200, y: 200}
+  m_MaxSize: {x: 4000, y: 4000}
+  m_TitleContent:
+    m_Text: Game
+    m_Image: {fileID: 4621777727084837110, guid: 0000000000000000d000000000000000,
+      type: 0}
+    m_Tooltip: 
+  m_Pos:
+    serializedVersion: 2
+    x: 824.5
+    y: 72
+    width: 1094.5
+    height: 500
+  m_ViewDataDictionary: {fileID: 0}
+  m_OverlayCanvas:
+    m_LastAppliedPresetName: Default
+    m_SaveData: []
+    m_OverlaysVisible: 1
+  m_SerializedViewNames: []
+  m_SerializedViewValues: []
+  m_PlayModeViewName: GameView
+  m_ShowGizmos: 0
+  m_TargetDisplay: 0
+  m_ClearColor: {r: 0, g: 0, b: 0, a: 0}
+  m_TargetSize: {x: 1094.5, y: 479}
+  m_TextureFilterMode: 0
+  m_TextureHideFlags: 61
+  m_RenderIMGUI: 1
+  m_EnterPlayModeBehavior: 0
+  m_UseMipMap: 0
+  m_VSyncEnabled: 0
+  m_Gizmos: 0
+  m_Stats: 0
+  m_SelectedSizes: 00000000000000000000000000000000000000000000000000000000000000000000000000000000
+  m_ZoomArea:
+    m_HRangeLocked: 0
+    m_VRangeLocked: 0
+    hZoomLockedByDefault: 0
+    vZoomLockedByDefault: 0
+    m_HBaseRangeMin: -273.625
+    m_HBaseRangeMax: 273.625
+    m_VBaseRangeMin: -119.75
+    m_VBaseRangeMax: 119.75
+    m_HAllowExceedBaseRangeMin: 1
+    m_HAllowExceedBaseRangeMax: 1
+    m_VAllowExceedBaseRangeMin: 1
+    m_VAllowExceedBaseRangeMax: 1
+    m_ScaleWithWindow: 0
+    m_HSlider: 0
+    m_VSlider: 0
+    m_IgnoreScrollWheelUntilClicked: 0
+    m_EnableMouseInput: 0
+    m_EnableSliderZoomHorizontal: 0
+    m_EnableSliderZoomVertical: 0
+    m_UniformScale: 1
+    m_UpDirection: 1
+    m_DrawArea:
+      serializedVersion: 2
+      x: 0
+      y: 21
+      width: 1094.5
+      height: 479
+    m_Scale: {x: 2, y: 2}
+    m_Translation: {x: 547.25, y: 239.5}
+    m_MarginLeft: 0
+    m_MarginRight: 0
+    m_MarginTop: 0
+    m_MarginBottom: 0
+    m_LastShownAreaInsideMargins:
+      serializedVersion: 2
+      x: -273.625
+      y: -119.75
+      width: 547.25
+      height: 239.5
+    m_MinimalGUI: 1
+  m_defaultScale: 2
+  m_LastWindowPixelSize: {x: 2189, y: 1000}
+  m_ClearInEditMode: 1
+  m_NoCameraWarning: 1
+  m_LowResolutionForAspectRatios: 01000000000000000000
+  m_XRRenderMode: 0
+  m_RenderTexture: {fileID: 0}
+--- !u!114 &21
+MonoBehaviour:
+  m_ObjectHideFlags: 52
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 1
+  m_Script: {fileID: 12003, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_MinSize: {x: 100, y: 100}
+  m_MaxSize: {x: 4000, y: 4000}
+  m_TitleContent:
+    m_Text: Console
+    m_Image: {fileID: -4950941429401207979, guid: 0000000000000000d000000000000000,
+      type: 0}
+    m_Tooltip: 
+  m_Pos:
+    serializedVersion: 2
+    x: 824.5
+    y: 593
+    width: 1094.5
+    height: 398
+  m_ViewDataDictionary: {fileID: 0}
+  m_OverlayCanvas:
+    m_LastAppliedPresetName: Default
+    m_SaveData: []
+    m_OverlaysVisible: 1