Răsfoiți Sursa

ai框架提交,附带一个小例子,登录进游戏,角色会自动巡逻10秒,停下来攻击5秒,然后再巡逻10秒,一直循环下去
注意AIConfig表中,每个ai是一个sheet,表中可以配置多个ai

tanghai 4 ani în urmă
părinte
comite
30b147abb1
54 a modificat fișierele cu 823 adăugiri și 104 ștergeri
  1. 1 0
      Client-Server.sln.DotSettings
  2. 4 0
      Config/AIConfigCategory.bytes
  3. BIN
      Excel/AIConfig.xlsx
  4. BIN
      Excel/StartSceneConfig.xlsx
  5. 8 3
      Proto/OuterMessage.proto
  6. 1 1
      Server/Hotfix/Demo/C2M_PathfindingResultHandler.cs
  7. 15 0
      Server/Hotfix/Demo/C2M_StopHandler.cs
  8. 31 26
      Server/Hotfix/Demo/Move/MoveHelper.cs
  9. 4 2
      Server/Hotfix/Server.Hotfix.csproj
  10. 91 0
      Server/Model/Generate/Config/AIConfig.cs
  11. 13 4
      Server/Model/Generate/Message/OuterMessage.cs
  12. 18 17
      Server/Model/Generate/Message/OuterOpcode.cs
  13. 4 0
      Server/Model/Server.Model.csproj
  14. 0 6
      Tools/ExcelExporter/ProtoObject.cs
  15. 4 0
      Unity/Assets/Bundles/Config/AIConfigCategory.bytes
  16. 7 0
      Unity/Assets/Bundles/Config/AIConfigCategory.bytes.meta
  17. 8 0
      Unity/Assets/Hotfix/Demo/AI.meta
  18. 45 0
      Unity/Assets/Hotfix/Demo/AI/AI_Attack.cs
  19. 11 0
      Unity/Assets/Hotfix/Demo/AI/AI_Attack.cs.meta
  20. 42 0
      Unity/Assets/Hotfix/Demo/AI/AI_XunLuo.cs
  21. 11 0
      Unity/Assets/Hotfix/Demo/AI/AI_XunLuo.cs.meta
  22. 17 0
      Unity/Assets/Hotfix/Demo/AI/XunLuoPathComponentSystem.cs
  23. 11 0
      Unity/Assets/Hotfix/Demo/AI/XunLuoPathComponentSystem.cs.meta
  24. 4 0
      Unity/Assets/Hotfix/Demo/MapHelper.cs
  25. 2 2
      Unity/Assets/Hotfix/Demo/Move/MoveHelper.cs
  26. 4 0
      Unity/Assets/Hotfix/Demo/Unit/UnitFactory.cs
  27. 8 0
      Unity/Assets/Hotfix/Module/AI.meta
  28. 80 0
      Unity/Assets/Hotfix/Module/AI/AIComponentSystem.cs
  29. 11 0
      Unity/Assets/Hotfix/Module/AI/AIComponentSystem.cs.meta
  30. 55 0
      Unity/Assets/Hotfix/Module/AI/AIDispatcherComponentSystem.cs
  31. 11 0
      Unity/Assets/Hotfix/Module/AI/AIDispatcherComponentSystem.cs.meta
  32. 2 0
      Unity/Assets/HotfixView/AppStart_Init.cs
  33. 0 17
      Unity/Assets/HotfixView/Opera/OperaComponentSystem.cs
  34. 1 0
      Unity/Assets/HotfixView/Scene/SceneFactory.cs
  35. 1 1
      Unity/Assets/Model/Core/Object/Object.cs
  36. 8 0
      Unity/Assets/Model/Demo/AI.meta
  37. 11 0
      Unity/Assets/Model/Demo/AI/XunLuoPathComponent.cs
  38. 11 0
      Unity/Assets/Model/Demo/AI/XunLuoPathComponent.cs.meta
  39. 91 0
      Unity/Assets/Model/Generate/Config/AIConfig.cs
  40. 11 0
      Unity/Assets/Model/Generate/Config/AIConfig.cs.meta
  41. 13 4
      Unity/Assets/Model/Generate/Message/OuterMessage.cs
  42. 18 17
      Unity/Assets/Model/Generate/Message/OuterOpcode.cs
  43. 8 0
      Unity/Assets/Model/Module/AI.meta
  44. 18 0
      Unity/Assets/Model/Module/AI/AAIHandler.cs
  45. 11 0
      Unity/Assets/Model/Module/AI/AAIHandler.cs.meta
  46. 14 0
      Unity/Assets/Model/Module/AI/AIComponent.cs
  47. 11 0
      Unity/Assets/Model/Module/AI/AIComponent.cs.meta
  48. 35 0
      Unity/Assets/Model/Module/AI/AIConfig.cs
  49. 11 0
      Unity/Assets/Model/Module/AI/AIConfig.cs.meta
  50. 11 0
      Unity/Assets/Model/Module/AI/AIDispatcherComponent.cs
  51. 11 0
      Unity/Assets/Model/Module/AI/AIDispatcherComponent.cs.meta
  52. 2 1
      Unity/Assets/Model/Module/Message/OpcodeHelper.cs
  53. 1 1
      Unity/Packages/packages-lock.json
  54. 2 2
      Unity/ProjectSettings/ProjectVersion.txt

+ 1 - 0
Client-Server.sln.DotSettings

@@ -404,6 +404,7 @@ II.2.12 <HandlesEvent />
 	<s:Boolean x:Key="/Default/Environment/SearchAndNavigation/AutoExpandResults/@EntryValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SearchAndNavigation/MergeOccurences/@EntryValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SearchAndNavigation/OpenPreviewTabForSelectedItemInFindResults/@EntryValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EdotCover_002EInteractive_002ECore_002EFilterManagement_002EMigration_002EGlobalFilterSettingsManagerMigrateSettings/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECpp_002EDaemon_002EInlayHints_002EParameterHints_002ECppParameterNameHintsOptionsOptionsMigration/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECSharp_002EParameterNameHints_002ECSharpParameterNameHintsOptionsMigration/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002EInlayHints_002EInlayHintsOptionsMigration/@EntryIndexedValue">True</s:Boolean>

+ 4 - 0
Config/AIConfigCategory.bytes

@@ -0,0 +1,4 @@
+
+e"	AI_Attack
+f"	AI_XunLuo
+É"	AI_XunLuo

BIN
Excel/AIConfig.xlsx


BIN
Excel/StartSceneConfig.xlsx


+ 8 - 3
Proto/OuterMessage.proto

@@ -64,20 +64,25 @@ message M2C_CreateUnits // IActorMessage
 {
 	int32 RpcId = 90;
 	int64 ActorId = 93;
-    repeated UnitInfo Units = 1;
+    repeated UnitInfo Units = 2;
 }
 
 message C2M_PathfindingResult // IActorLocationMessage
 {
 	int32 RpcId = 90;
 	int64 ActorId = 93;
-	int64 Id = 94;
-	
+		
 	float X = 1;
 	float Y = 2;
 	float Z = 3;
 }
 
+message C2M_Stop // IActorLocationMessage
+{    
+	int32 RpcId = 90;
+	int64 ActorId = 93;
+}
+
 message M2C_PathfindingResult // IActorMessage
 {
 	int64 ActorId = 93;

+ 1 - 1
Server/Hotfix/Demo/C2M_PathfindingResultHandler.cs

@@ -10,7 +10,7 @@ namespace ET
 		{
 			Vector3 target = new Vector3(message.X, message.Y, message.Z);
 
-			MoveHelper.FindPathMoveToAsync(unit, target).Coroutine();
+			unit.FindPathMoveToAsync(target).Coroutine();
 			
 			await ETTask.CompletedTask;
 		}

+ 15 - 0
Server/Hotfix/Demo/C2M_StopHandler.cs

@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace ET
+{
+	[ActorMessageHandler]
+	public class C2M_StopHandler : AMActorLocationHandler<Unit, C2M_Stop>
+	{
+		protected override async ETTask Run(Unit unit, C2M_Stop message)
+		{
+			unit.Stop(0);
+			await ETTask.CompletedTask;
+		}
+	}
+}

+ 31 - 26
Server/Hotfix/Demo/Move/MoveHelper.cs

@@ -9,43 +9,48 @@ namespace ET
         public static async ETTask FindPathMoveToAsync(this Unit unit, Vector3 target, ETCancellationToken cancellationToken = null)
         {
             float speed = unit.GetComponent<NumericComponent>().GetAsFloat(NumericType.Speed);
-            if (speed < 0.001)
+            if (speed < 0.01)
             {
                 unit.SendStop(-1);
                 return;
             }
+
+            using var list = ListComponent<Vector3>.Create();
             
-            using (var list = ListComponent<Vector3>.Create())
-            {
-                unit.Domain.GetComponent<RecastPathComponent>().SearchPath(10001, unit.Position, target, list.List);
+            unit.Domain.GetComponent<RecastPathComponent>().SearchPath(10001, unit.Position, target, list.List);
 
-                List<Vector3> path = list.List;
-                if (path.Count < 2)
-                {
-                    unit.SendStop(-2);
-                    return;
-                }
+            List<Vector3> path = list.List;
+            if (path.Count < 2)
+            {
+                unit.SendStop(0);
+                return;
+            }
                 
-                // 广播寻路路径
-                M2C_PathfindingResult m2CPathfindingResult = new M2C_PathfindingResult();
-                m2CPathfindingResult.Id = unit.Id;
-                for (int i = 0; i < list.List.Count; ++i)
-                {
-                    Vector3 vector3 = list.List[i];
-                    m2CPathfindingResult.Xs.Add(vector3.x);
-                    m2CPathfindingResult.Ys.Add(vector3.y);
-                    m2CPathfindingResult.Zs.Add(vector3.z);
-                }
-                MessageHelper.Broadcast(unit, m2CPathfindingResult);
+            // 广播寻路路径
+            M2C_PathfindingResult m2CPathfindingResult = new M2C_PathfindingResult();
+            m2CPathfindingResult.Id = unit.Id;
+            for (int i = 0; i < list.List.Count; ++i)
+            {
+                Vector3 vector3 = list.List[i];
+                m2CPathfindingResult.Xs.Add(vector3.x);
+                m2CPathfindingResult.Ys.Add(vector3.y);
+                m2CPathfindingResult.Zs.Add(vector3.z);
+            }
+            MessageHelper.Broadcast(unit, m2CPathfindingResult);
 
-                bool ret = await unit.GetComponent<MoveComponent>().MoveToAsync(path, speed);
-                if (ret) // 如果返回false,说明被其它移动取消了,这时候不需要通知客户端stop
-                {
-                    unit.SendStop(0);
-                }
+            bool ret = await unit.GetComponent<MoveComponent>().MoveToAsync(path, speed);
+            if (ret) // 如果返回false,说明被其它移动取消了,这时候不需要通知客户端stop
+            {
+                unit.SendStop(0);
             }
         }
 
+        public static void Stop(this Unit unit, int error)
+        {
+            unit.GetComponent<MoveComponent>().Stop();
+            unit.SendStop(error);
+        }
+
         public static void SendStop(this Unit unit, int error)
         {
             MessageHelper.Broadcast(unit, new M2C_Stop()

+ 4 - 2
Server/Hotfix/Server.Hotfix.csproj

@@ -47,8 +47,10 @@
     <Compile Include="..\..\Unity\Assets\Hotfix\Module\Numeric\NumericWatcher_Hp_ShowUI.cs">
       <Link>Module\Numeric\NumericWatcher_Hp_ShowUI.cs</Link>
     </Compile>
-    <EmbeddedResource Remove="Other\**" />
-    <None Remove="Other\**" />
+
+    <Compile Include="..\..\Unity\Assets\Hotfix\Module\AI\**\*.cs">
+      <Link>Module\AI\%(RecursiveDir)%(FileName)%(Extension)</Link>
+    </Compile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Model\Server.Model.csproj" />

+ 91 - 0
Server/Model/Generate/Config/AIConfig.cs

@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using MongoDB.Bson.Serialization.Attributes;
+using ProtoBuf;
+
+namespace ET
+{
+    [ProtoContract]
+    [Config]
+    public partial class AIConfigCategory : ProtoObject
+    {
+        public static AIConfigCategory Instance;
+		
+        [ProtoIgnore]
+        [BsonIgnore]
+        private Dictionary<int, AIConfig> dict = new Dictionary<int, AIConfig>();
+		
+        [BsonElement]
+        [ProtoMember(1)]
+        private List<AIConfig> list = new List<AIConfig>();
+		
+        public AIConfigCategory()
+        {
+            Instance = this;
+        }
+		
+		[ProtoAfterDeserialization]
+        public void AfterDeserialization()
+        {
+            foreach (AIConfig config in list)
+            {
+                this.dict.Add(config.Id, config);
+            }
+            list.Clear();
+            this.EndInit();
+        }
+		
+        public AIConfig Get(int id)
+        {
+            this.dict.TryGetValue(id, out AIConfig item);
+
+            if (item == null)
+            {
+                throw new Exception($"配置找不到,配置表名: {nameof (AIConfig)},配置id: {id}");
+            }
+
+            return item;
+        }
+		
+        public bool Contain(int id)
+        {
+            return this.dict.ContainsKey(id);
+        }
+
+        public Dictionary<int, AIConfig> GetAll()
+        {
+            return this.dict;
+        }
+
+        public AIConfig GetOne()
+        {
+            if (this.dict == null || this.dict.Count <= 0)
+            {
+                return null;
+            }
+            return this.dict.Values.GetEnumerator().Current;
+        }
+    }
+
+    [ProtoContract]
+	public partial class AIConfig: ProtoObject, IConfig
+	{
+		[ProtoMember(1, IsRequired  = true)]
+		public int Id { get; set; }
+		[ProtoMember(2, IsRequired  = true)]
+		public int AIConfigId { get; set; }
+		[ProtoMember(3, IsRequired  = true)]
+		public int Order { get; set; }
+		[ProtoMember(4, IsRequired  = true)]
+		public string Name { get; set; }
+		[ProtoMember(5, IsRequired  = true)]
+		public int[] NodeParams { get; set; }
+
+
+		[ProtoAfterDeserialization]
+        public void AfterDeserialization()
+        {
+            this.EndInit();
+        }
+	}
+}

+ 13 - 4
Server/Model/Generate/Message/OuterMessage.cs

@@ -140,7 +140,7 @@ namespace ET
 		[ProtoMember(93)]
 		public long ActorId { get; set; }
 
-		[ProtoMember(1)]
+		[ProtoMember(2)]
 		public List<UnitInfo> Units = new List<UnitInfo>();
 
 	}
@@ -155,9 +155,6 @@ namespace ET
 		[ProtoMember(93)]
 		public long ActorId { get; set; }
 
-		[ProtoMember(94)]
-		public long Id { get; set; }
-
 		[ProtoMember(1)]
 		public float X { get; set; }
 
@@ -169,6 +166,18 @@ namespace ET
 
 	}
 
+	[Message(OuterOpcode.C2M_Stop)]
+	[ProtoContract]
+	public partial class C2M_Stop: Object, IActorLocationMessage
+	{
+		[ProtoMember(90)]
+		public int RpcId { get; set; }
+
+		[ProtoMember(93)]
+		public long ActorId { get; set; }
+
+	}
+
 	[Message(OuterOpcode.M2C_PathfindingResult)]
 	[ProtoContract]
 	public partial class M2C_PathfindingResult: Object, IActorMessage

+ 18 - 17
Server/Model/Generate/Message/OuterOpcode.cs

@@ -11,22 +11,23 @@ namespace ET
 		 public const ushort UnitInfo = 20007;
 		 public const ushort M2C_CreateUnits = 20008;
 		 public const ushort C2M_PathfindingResult = 20009;
-		 public const ushort M2C_PathfindingResult = 20010;
-		 public const ushort M2C_Stop = 20011;
-		 public const ushort C2G_Ping = 20012;
-		 public const ushort G2C_Ping = 20013;
-		 public const ushort G2C_Test = 20014;
-		 public const ushort C2M_Reload = 20015;
-		 public const ushort M2C_Reload = 20016;
-		 public const ushort C2R_Login = 20017;
-		 public const ushort R2C_Login = 20018;
-		 public const ushort C2G_LoginGate = 20019;
-		 public const ushort G2C_LoginGate = 20020;
-		 public const ushort G2C_TestHotfixMessage = 20021;
-		 public const ushort C2M_TestActorRequest = 20022;
-		 public const ushort M2C_TestActorResponse = 20023;
-		 public const ushort PlayerInfo = 20024;
-		 public const ushort C2G_PlayerInfo = 20025;
-		 public const ushort G2C_PlayerInfo = 20026;
+		 public const ushort C2M_Stop = 20010;
+		 public const ushort M2C_PathfindingResult = 20011;
+		 public const ushort M2C_Stop = 20012;
+		 public const ushort C2G_Ping = 20013;
+		 public const ushort G2C_Ping = 20014;
+		 public const ushort G2C_Test = 20015;
+		 public const ushort C2M_Reload = 20016;
+		 public const ushort M2C_Reload = 20017;
+		 public const ushort C2R_Login = 20018;
+		 public const ushort R2C_Login = 20019;
+		 public const ushort C2G_LoginGate = 20020;
+		 public const ushort G2C_LoginGate = 20021;
+		 public const ushort G2C_TestHotfixMessage = 20022;
+		 public const ushort C2M_TestActorRequest = 20023;
+		 public const ushort M2C_TestActorResponse = 20024;
+		 public const ushort PlayerInfo = 20025;
+		 public const ushort C2G_PlayerInfo = 20026;
+		 public const ushort G2C_PlayerInfo = 20027;
 	}
 }

+ 4 - 0
Server/Model/Server.Model.csproj

@@ -37,6 +37,10 @@
     <Compile Include="..\..\Unity\Assets\Model\Module\Config\**\*.cs">
       <Link>Module\Config\%(RecursiveDir)%(FileName)%(Extension)</Link>
     </Compile>
+
+    <Compile Include="..\..\Unity\Assets\Model\Module\AI\**\*.cs">
+      <Link>Module\AI\%(RecursiveDir)%(FileName)%(Extension)</Link>
+    </Compile>
     
     <Compile Remove="Libs\**" />
     

+ 0 - 6
Tools/ExcelExporter/ProtoObject.cs

@@ -14,12 +14,6 @@ namespace ET
         {
         }
 
-        [ProtoAfterDeserialization]
-        public virtual void AfterDeserialization()
-        {
-            this.EndInit();
-        }
-
         public virtual void EndInit()
         {
         }

+ 4 - 0
Unity/Assets/Bundles/Config/AIConfigCategory.bytes

@@ -0,0 +1,4 @@
+
+e"	AI_Attack
+f"	AI_XunLuo
+É"	AI_XunLuo

+ 7 - 0
Unity/Assets/Bundles/Config/AIConfigCategory.bytes.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 277d58db3067742a7b32f9994984b3bc
+TextScriptImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Hotfix/Demo/AI.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0c430df865ee84f2f9348d817d6596a9
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 45 - 0
Unity/Assets/Hotfix/Demo/AI/AI_Attack.cs

@@ -0,0 +1,45 @@
+using UnityEngine;
+
+namespace ET
+{
+    public class AI_Attack: AAIHandler
+    {
+        public override int Check(AIComponent aiComponent, AIConfig aiConfig)
+        {
+            long sec = TimeHelper.ClientNow() / 1000 % 15;
+            if (sec >= 10)
+            {
+                return 0;
+            }
+            return 1;
+        }
+
+        public override async ETVoid Execute(AIComponent aiComponent, AIConfig aiConfig, ETCancellationToken cancellationToken)
+        {
+            Scene zoneScene = aiComponent.DomainScene();
+
+            Unit myUnit = zoneScene.GetComponent<UnitComponent>().MyUnit;
+            if (myUnit == null)
+            {
+                return;
+            }
+
+            // 停在当前位置
+            zoneScene.GetComponent<SessionComponent>().Session.Send(new C2M_Stop());
+            
+            Log.Debug("开始攻击");
+
+            for (int i = 0; i < 100000; ++i)
+            {
+                Log.Debug($"攻击: {i}次");
+
+                // 因为协程可能被中断,任何协程都要传入cancellationToken,判断如果是中断则要返回
+                bool timeRet = await TimerComponent.Instance.WaitAsync(1000, cancellationToken);
+                if (!timeRet)
+                {
+                    return;
+                }
+            }
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Hotfix/Demo/AI/AI_Attack.cs.meta

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

+ 42 - 0
Unity/Assets/Hotfix/Demo/AI/AI_XunLuo.cs

@@ -0,0 +1,42 @@
+using UnityEngine;
+
+namespace ET
+{
+    public class AI_XunLuo: AAIHandler
+    {
+        public override int Check(AIComponent aiComponent, AIConfig aiConfig)
+        {
+            long sec = TimeHelper.ClientNow() / 1000 % 15;
+            if (sec < 10)
+            {
+                return 0;
+            }
+            return 1;
+        }
+
+        public override async ETVoid Execute(AIComponent aiComponent, AIConfig aiConfig, ETCancellationToken cancellationToken)
+        {
+            Scene zoneScene = aiComponent.DomainScene();
+
+            Unit myUnit = zoneScene.GetComponent<UnitComponent>().MyUnit;
+            if (myUnit == null)
+            {
+                return;
+            }
+            
+            Log.Debug("开始巡逻");
+
+            while (true)
+            {
+                XunLuoPathComponent xunLuoPathComponent = myUnit.GetComponent<XunLuoPathComponent>();
+                Vector3 nextTarget = xunLuoPathComponent.GetCurrent();
+                int ret = await myUnit.MoveToAsync(nextTarget, cancellationToken);
+                if (ret != 0)
+                {
+                    return;
+                }
+                xunLuoPathComponent.MoveNext();
+            }
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Hotfix/Demo/AI/AI_XunLuo.cs.meta

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

+ 17 - 0
Unity/Assets/Hotfix/Demo/AI/XunLuoPathComponentSystem.cs

@@ -0,0 +1,17 @@
+using UnityEngine;
+
+namespace ET
+{
+    public static class XunLuoPathComponentSystem
+    {
+        public static Vector3 GetCurrent(this XunLuoPathComponent self)
+        {
+            return self.path[self.Index];
+        }
+        
+        public static void MoveNext(this XunLuoPathComponent self)
+        {
+            self.Index = ++self.Index % self.path.Length;
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Hotfix/Demo/AI/XunLuoPathComponentSystem.cs.meta

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

+ 4 - 0
Unity/Assets/Hotfix/Demo/MapHelper.cs

@@ -10,6 +10,10 @@ namespace ET
             try
             {
                 G2C_EnterMap g2CEnterMap = await zoneScene.GetComponent<SessionComponent>().Session.Call(new C2G_EnterMap()) as G2C_EnterMap;
+
+                UnitComponent unitComponent = zoneScene.GetComponent<UnitComponent>();
+                unitComponent.MyUnit = unitComponent.Get(g2CEnterMap.UnitId);
+                
                 Game.EventSystem.Publish(new EventType.EnterMapFinish() {ZoneScene = zoneScene}).Coroutine();
             }
             catch (Exception e)

+ 2 - 2
Unity/Assets/Hotfix/Demo/Move/MoveHelper.cs

@@ -8,7 +8,7 @@ namespace ET
         // 可以多次调用,多次调用的话会取消上一次的协程
         public static async ETTask<int> MoveToAsync(this Unit unit, Vector3 targetPos, ETCancellationToken cancellationToken = null)
         {
-            C2M_PathfindingResult msg = new C2M_PathfindingResult();
+            C2M_PathfindingResult msg = new C2M_PathfindingResult() {X = targetPos.x, Y = targetPos.y, Z = targetPos.z};
             unit.Domain.GetComponent<SessionComponent>().Session.Send(msg);
 
             ObjectWait objectWait = unit.GetComponent<ObjectWait>();
@@ -17,7 +17,7 @@ namespace ET
             objectWait.Notify(new WaitType.Wait_UnitStop() { Error = WaitTypeError.Cancel });
             
             // 一直等到unit发送stop
-            WaitType.Wait_UnitStop waitUnitStop = await objectWait.Wait<WaitType.Wait_UnitStop>();
+            WaitType.Wait_UnitStop waitUnitStop = await objectWait.Wait<WaitType.Wait_UnitStop>(cancellationToken);
             return waitUnitStop.Error;
         }
     }

+ 4 - 0
Unity/Assets/Hotfix/Demo/Unit/UnitFactory.cs

@@ -16,6 +16,10 @@ namespace ET
 		        numericComponent.Set((NumericType)unitInfo.Ks[i], unitInfo.Vs[i]);
 	        }
 
+	        unit.AddComponent<ObjectWait>();
+
+	        unit.AddComponent<XunLuoPathComponent>();
+
 	        UnitComponent unitComponent = domain.GetComponent<UnitComponent>();
             unitComponent.Add(unit);
             

+ 8 - 0
Unity/Assets/Hotfix/Module/AI.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 490f7b30b1f804e9882ec3deb25b6013
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 80 - 0
Unity/Assets/Hotfix/Module/AI/AIComponentSystem.cs

@@ -0,0 +1,80 @@
+using System;
+using UnityEngine;
+
+namespace ET
+{
+    [ObjectSystem]
+    public class AIComponentAwakeSystem: AwakeSystem<AIComponent, int>
+    {
+        public override void Awake(AIComponent self, int aiConfigId)
+        {
+            self.AIConfigId = aiConfigId;
+            self.Timer = TimerComponent.Instance.NewRepeatedTimer(1000, self.Check);
+        }
+    }
+
+    [ObjectSystem]
+    public class AIComponentDestroySystem: DestroySystem<AIComponent>
+    {
+        public override void Destroy(AIComponent self)
+        {
+            TimerComponent.Instance.Remove(ref self.Timer);
+            self.CancellationToken?.Cancel();
+            self.CancellationToken = null;
+            self.Current = 0;
+        }
+    }
+
+    public static class AIComponentSystem
+    {
+        public static void Check(this AIComponent self)
+        {
+            if (self.Parent == null)
+            {
+                TimerComponent.Instance.Remove(ref self.Timer);
+                return;
+            }
+
+            var oneAI = AIConfigCategory.Instance.AIConfigs[self.AIConfigId];
+
+            foreach (AIConfig aiConfig in oneAI.Values)
+            {
+
+                AIDispatcherComponent.Instance.AIHandlers.TryGetValue(aiConfig.Name, out AAIHandler aaiHandler);
+
+                if (aaiHandler == null)
+                {
+                    Log.Error($"not found aihandler: {aiConfig.Name}");
+                    continue;
+                }
+
+                int ret = aaiHandler.Check(self, aiConfig);
+                if (ret != 0)
+                {
+                    continue;
+                }
+
+                if (self.Current == aiConfig.Id)
+                {
+                    break;
+                }
+
+                self.Cancel(); // 取消之前的行为
+                ETCancellationToken cancellationToken = new ETCancellationToken();
+                self.CancellationToken = cancellationToken;
+                self.Current = aiConfig.Id;
+
+                aaiHandler.Execute(self, aiConfig, cancellationToken).Coroutine();
+                return;
+            }
+            
+        }
+
+        private static void Cancel(this AIComponent self)
+        {
+            self.CancellationToken?.Cancel();
+            self.Current = 0;
+            self.CancellationToken = null;
+        }
+    }
+} 

+ 11 - 0
Unity/Assets/Hotfix/Module/AI/AIComponentSystem.cs.meta

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

+ 55 - 0
Unity/Assets/Hotfix/Module/AI/AIDispatcherComponentSystem.cs

@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ET
+{
+    [ObjectSystem]
+    public class AIDispatcherComponentAwakeSystem: AwakeSystem<AIDispatcherComponent>
+    {
+        public override void Awake(AIDispatcherComponent self)
+        {
+            AIDispatcherComponent.Instance = self;
+            self.Load();
+        }
+    }
+
+    [ObjectSystem]
+    public class AIDispatcherComponentLoadSystem: LoadSystem<AIDispatcherComponent>
+    {
+        public override void Load(AIDispatcherComponent self)
+        {
+            self.Load();
+        }
+    }
+
+    [ObjectSystem]
+    public class AIDispatcherComponentDestroySystem: DestroySystem<AIDispatcherComponent>
+    {
+        public override void Destroy(AIDispatcherComponent self)
+        {
+            self.AIHandlers.Clear();
+            AIDispatcherComponent.Instance = null;
+        }
+    }
+
+    public static class AIDispatcherComponentSystem
+    {
+        public static void Load(this AIDispatcherComponent self)
+        {
+            self.AIHandlers.Clear();
+
+            var types = Game.EventSystem.GetTypes(typeof (AIHandlerAttribute));
+            foreach (Type type in types)
+            {
+                AAIHandler aaiHandler = Activator.CreateInstance(type) as AAIHandler;
+                if (aaiHandler == null)
+                {
+                    Log.Error($"robot ai is not AAIHandler: {type.Name}");
+                    continue;
+                }
+                self.AIHandlers.Add(type.Name, aaiHandler);
+            }
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Hotfix/Module/AI/AIDispatcherComponentSystem.cs.meta

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

+ 2 - 0
Unity/Assets/HotfixView/AppStart_Init.cs

@@ -24,6 +24,8 @@ namespace ET
             
             Game.Scene.AddComponent<GlobalComponent>();
 
+            Game.Scene.AddComponent<AIDispatcherComponent>();
+
             ResourcesComponent.Instance.LoadBundle("unit.unity3d");
 
             Scene zoneScene = await SceneFactory.CreateZoneScene(1, "Process");

+ 0 - 17
Unity/Assets/HotfixView/Opera/OperaComponentSystem.cs

@@ -34,25 +34,8 @@ namespace ET
                     self.frameClickMap.Y = self.ClickPoint.y;
                     self.frameClickMap.Z = self.ClickPoint.z;
                     self.DomainScene().GetComponent<SessionComponent>().Session.Send(self.frameClickMap);
-
-                    // 测试actor rpc消息
-                    self.TestActor().Coroutine();
                 }
             }
         }
-
-        public static async ETVoid TestActor(this OperaComponent self)
-        {
-            try
-            {
-                M2C_TestActorResponse response = (M2C_TestActorResponse)await self.Domain.GetComponent<SessionComponent>().Session.Call(
-                    new C2M_TestActorRequest() { Info = "actor rpc request" });
-                Log.Info(response.Info);
-            }
-            catch (Exception e)
-            {
-                Log.Error(e);
-            }
-        }
     }
 }

+ 1 - 0
Unity/Assets/HotfixView/Scene/SceneFactory.cs

@@ -8,6 +8,7 @@ namespace ET
             zoneScene.AddComponent<ZoneSceneFlagComponent>();
             zoneScene.AddComponent<NetKcpComponent>();
             zoneScene.AddComponent<UnitComponent>();
+            zoneScene.AddComponent<AIComponent, int>(1);
             
             // UI层的初始化
             await Game.EventSystem.Publish(new EventType.AfterCreateZoneScene() {ZoneScene = zoneScene});

+ 1 - 1
Unity/Assets/Model/Core/Object/Object.cs

@@ -53,7 +53,7 @@ namespace ET
             }
 #endif
         }
-
+        
         public override string ToString()
         {
             return JsonHelper.ToJson(this);

+ 8 - 0
Unity/Assets/Model/Demo/AI.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: bc7b2c776a049435694c2242436e6183
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 11 - 0
Unity/Assets/Model/Demo/AI/XunLuoPathComponent.cs

@@ -0,0 +1,11 @@
+using UnityEngine;
+
+namespace ET
+{
+    public class XunLuoPathComponent: Entity
+    {
+        public Vector3[] path = new Vector3[] { new Vector3(0, 0, 0), new Vector3(20, 0, 0), new Vector3(20, 0, 20), new Vector3(0, 0, 20), };
+
+        public int Index;
+    }
+}

+ 11 - 0
Unity/Assets/Model/Demo/AI/XunLuoPathComponent.cs.meta

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

+ 91 - 0
Unity/Assets/Model/Generate/Config/AIConfig.cs

@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using MongoDB.Bson.Serialization.Attributes;
+using ProtoBuf;
+
+namespace ET
+{
+    [ProtoContract]
+    [Config]
+    public partial class AIConfigCategory : ProtoObject
+    {
+        public static AIConfigCategory Instance;
+		
+        [ProtoIgnore]
+        [BsonIgnore]
+        private Dictionary<int, AIConfig> dict = new Dictionary<int, AIConfig>();
+		
+        [BsonElement]
+        [ProtoMember(1)]
+        private List<AIConfig> list = new List<AIConfig>();
+		
+        public AIConfigCategory()
+        {
+            Instance = this;
+        }
+		
+		[ProtoAfterDeserialization]
+        public void AfterDeserialization()
+        {
+            foreach (AIConfig config in list)
+            {
+                this.dict.Add(config.Id, config);
+            }
+            list.Clear();
+            this.EndInit();
+        }
+		
+        public AIConfig Get(int id)
+        {
+            this.dict.TryGetValue(id, out AIConfig item);
+
+            if (item == null)
+            {
+                throw new Exception($"配置找不到,配置表名: {nameof (AIConfig)},配置id: {id}");
+            }
+
+            return item;
+        }
+		
+        public bool Contain(int id)
+        {
+            return this.dict.ContainsKey(id);
+        }
+
+        public Dictionary<int, AIConfig> GetAll()
+        {
+            return this.dict;
+        }
+
+        public AIConfig GetOne()
+        {
+            if (this.dict == null || this.dict.Count <= 0)
+            {
+                return null;
+            }
+            return this.dict.Values.GetEnumerator().Current;
+        }
+    }
+
+    [ProtoContract]
+	public partial class AIConfig: ProtoObject, IConfig
+	{
+		[ProtoMember(1, IsRequired  = true)]
+		public int Id { get; set; }
+		[ProtoMember(2, IsRequired  = true)]
+		public int AIConfigId { get; set; }
+		[ProtoMember(3, IsRequired  = true)]
+		public int Order { get; set; }
+		[ProtoMember(4, IsRequired  = true)]
+		public string Name { get; set; }
+		[ProtoMember(5, IsRequired  = true)]
+		public int[] NodeParams { get; set; }
+
+
+		[ProtoAfterDeserialization]
+        public void AfterDeserialization()
+        {
+            this.EndInit();
+        }
+	}
+}

+ 11 - 0
Unity/Assets/Model/Generate/Config/AIConfig.cs.meta

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

+ 13 - 4
Unity/Assets/Model/Generate/Message/OuterMessage.cs

@@ -140,7 +140,7 @@ namespace ET
 		[ProtoMember(93)]
 		public long ActorId { get; set; }
 
-		[ProtoMember(1)]
+		[ProtoMember(2)]
 		public List<UnitInfo> Units = new List<UnitInfo>();
 
 	}
@@ -155,9 +155,6 @@ namespace ET
 		[ProtoMember(93)]
 		public long ActorId { get; set; }
 
-		[ProtoMember(94)]
-		public long Id { get; set; }
-
 		[ProtoMember(1)]
 		public float X { get; set; }
 
@@ -169,6 +166,18 @@ namespace ET
 
 	}
 
+	[Message(OuterOpcode.C2M_Stop)]
+	[ProtoContract]
+	public partial class C2M_Stop: Object, IActorLocationMessage
+	{
+		[ProtoMember(90)]
+		public int RpcId { get; set; }
+
+		[ProtoMember(93)]
+		public long ActorId { get; set; }
+
+	}
+
 	[Message(OuterOpcode.M2C_PathfindingResult)]
 	[ProtoContract]
 	public partial class M2C_PathfindingResult: Object, IActorMessage

+ 18 - 17
Unity/Assets/Model/Generate/Message/OuterOpcode.cs

@@ -11,22 +11,23 @@ namespace ET
 		 public const ushort UnitInfo = 20007;
 		 public const ushort M2C_CreateUnits = 20008;
 		 public const ushort C2M_PathfindingResult = 20009;
-		 public const ushort M2C_PathfindingResult = 20010;
-		 public const ushort M2C_Stop = 20011;
-		 public const ushort C2G_Ping = 20012;
-		 public const ushort G2C_Ping = 20013;
-		 public const ushort G2C_Test = 20014;
-		 public const ushort C2M_Reload = 20015;
-		 public const ushort M2C_Reload = 20016;
-		 public const ushort C2R_Login = 20017;
-		 public const ushort R2C_Login = 20018;
-		 public const ushort C2G_LoginGate = 20019;
-		 public const ushort G2C_LoginGate = 20020;
-		 public const ushort G2C_TestHotfixMessage = 20021;
-		 public const ushort C2M_TestActorRequest = 20022;
-		 public const ushort M2C_TestActorResponse = 20023;
-		 public const ushort PlayerInfo = 20024;
-		 public const ushort C2G_PlayerInfo = 20025;
-		 public const ushort G2C_PlayerInfo = 20026;
+		 public const ushort C2M_Stop = 20010;
+		 public const ushort M2C_PathfindingResult = 20011;
+		 public const ushort M2C_Stop = 20012;
+		 public const ushort C2G_Ping = 20013;
+		 public const ushort G2C_Ping = 20014;
+		 public const ushort G2C_Test = 20015;
+		 public const ushort C2M_Reload = 20016;
+		 public const ushort M2C_Reload = 20017;
+		 public const ushort C2R_Login = 20018;
+		 public const ushort R2C_Login = 20019;
+		 public const ushort C2G_LoginGate = 20020;
+		 public const ushort G2C_LoginGate = 20021;
+		 public const ushort G2C_TestHotfixMessage = 20022;
+		 public const ushort C2M_TestActorRequest = 20023;
+		 public const ushort M2C_TestActorResponse = 20024;
+		 public const ushort PlayerInfo = 20025;
+		 public const ushort C2G_PlayerInfo = 20026;
+		 public const ushort G2C_PlayerInfo = 20027;
 	}
 }

+ 8 - 0
Unity/Assets/Model/Module/AI.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 167c92d772b01476c983b16abfa46562
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 18 - 0
Unity/Assets/Model/Module/AI/AAIHandler.cs

@@ -0,0 +1,18 @@
+using System;
+
+namespace ET
+{
+    public class AIHandlerAttribute: BaseAttribute
+    {
+    }
+    
+    [AIHandler]
+    public abstract class AAIHandler
+    {
+        // 检查是否满足条件
+        public abstract int Check(AIComponent aiComponent, AIConfig aiConfig);
+
+        // 协程编写必须可以取消
+        public abstract ETVoid Execute(AIComponent aiComponent, AIConfig aiConfig, ETCancellationToken cancellationToken);
+    }
+}

+ 11 - 0
Unity/Assets/Model/Module/AI/AAIHandler.cs.meta

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

+ 14 - 0
Unity/Assets/Model/Module/AI/AIComponent.cs

@@ -0,0 +1,14 @@
+namespace ET
+{
+    // 客户端挂在ZoneScene上,服务端挂在Unit上
+    public class AIComponent: Entity
+    {
+        public int AIConfigId;
+        
+        public ETCancellationToken CancellationToken;
+
+        public long Timer;
+
+        public int Current;
+    }
+}

+ 11 - 0
Unity/Assets/Model/Module/AI/AIComponent.cs.meta

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

+ 35 - 0
Unity/Assets/Model/Module/AI/AIConfig.cs

@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+using MongoDB.Bson;
+using MongoDB.Bson.Serialization.Attributes;
+using ProtoBuf;
+
+namespace ET
+{
+	public partial class AIConfigCategory
+	{
+		public Dictionary<int, SortedDictionary<int, AIConfig>> AIConfigs = new Dictionary<int, SortedDictionary<int, AIConfig>>();
+
+		public SortedDictionary<int, AIConfig> GetAI(int aiConfigId)
+		{
+			return this.AIConfigs[aiConfigId];
+		}
+		
+		public override void EndInit()
+		{
+			base.EndInit();
+			
+			foreach (var kv in this.GetAll())
+			{
+				SortedDictionary<int, AIConfig> aiNodeConfig;
+				if (!this.AIConfigs.TryGetValue(kv.Value.AIConfigId, out aiNodeConfig))
+				{
+					aiNodeConfig = new SortedDictionary<int, AIConfig>();
+					this.AIConfigs.Add(kv.Value.AIConfigId, aiNodeConfig);
+				}
+				
+				aiNodeConfig.Add(kv.Key, kv.Value);
+			}
+		}
+	}
+}

+ 11 - 0
Unity/Assets/Model/Module/AI/AIConfig.cs.meta

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

+ 11 - 0
Unity/Assets/Model/Module/AI/AIDispatcherComponent.cs

@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace ET
+{
+    public class AIDispatcherComponent: Entity
+    {
+        public static AIDispatcherComponent Instance;
+        
+        public Dictionary<string, AAIHandler> AIHandlers = new Dictionary<string, AAIHandler>();
+    }
+}

+ 11 - 0
Unity/Assets/Model/Module/AI/AIDispatcherComponent.cs.meta

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

+ 2 - 1
Unity/Assets/Model/Module/Message/OpcodeHelper.cs

@@ -6,7 +6,8 @@ namespace ET
     {
         private static readonly HashSet<ushort> ignoreDebugLogMessageSet = new HashSet<ushort>
         {
-            
+            OuterOpcode.C2G_Ping,
+            OuterOpcode.G2C_Ping,
         };
 
         private static bool IsNeedLogMessage(ushort opcode)

+ 1 - 1
Unity/Packages/packages-lock.json

@@ -52,7 +52,7 @@
       "url": "https://packages.unity.cn"
     },
     "com.unity.test-framework": {
-      "version": "1.1.22",
+      "version": "1.1.24",
       "depth": 1,
       "source": "registry",
       "dependencies": {

+ 2 - 2
Unity/ProjectSettings/ProjectVersion.txt

@@ -1,2 +1,2 @@
-m_EditorVersion: 2020.3.0f1c1
-m_EditorVersionWithRevision: 2020.3.0f1c1 (1e553bf703d9)
+m_EditorVersion: 2020.3.3f1c1
+m_EditorVersionWithRevision: 2020.3.3f1c1 (a34b99c2c582)