BehaviorTreeComponent.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using UnityEngine;
  5. namespace Model
  6. {
  7. [ObjectSystem]
  8. public class BehaviorTreeComponentAwakeSystem : AwakeSystem<BehaviorTreeComponent>
  9. {
  10. public override void Awake(BehaviorTreeComponent self)
  11. {
  12. self.Awake();
  13. }
  14. }
  15. [ObjectSystem]
  16. public class BehaviorTreeComponentLoadSystem : LoadSystem<BehaviorTreeComponent>
  17. {
  18. public override void Load(BehaviorTreeComponent self)
  19. {
  20. self.Load();
  21. }
  22. }
  23. public class BehaviorTreeComponent : Component
  24. {
  25. public static BehaviorTreeComponent Instance;
  26. private Dictionary<string, Func<NodeProto, Node>> dictionary;
  27. private Dictionary<GameObject, BehaviorTree> treeCache;
  28. public void Awake()
  29. {
  30. Instance = this;
  31. this.Load();
  32. }
  33. public void Load()
  34. {
  35. this.dictionary = new Dictionary<string, Func<NodeProto, Node>>();
  36. this.treeCache = new Dictionary<GameObject, BehaviorTree>();
  37. Type[] types = DllHelper.GetMonoTypes();
  38. foreach (Type type in types)
  39. {
  40. object[] attrs = type.GetCustomAttributes(typeof(NodeAttribute), false);
  41. if (attrs.Length == 0)
  42. {
  43. continue;
  44. }
  45. Type classType = type;
  46. if (this.dictionary.ContainsKey(type.Name))
  47. {
  48. throw new Exception($"已经存在同类节点: {classType.Name}");
  49. }
  50. this.dictionary.Add(type.Name, config =>
  51. {
  52. Node node = (Node)Activator.CreateInstance(classType, config);
  53. try
  54. {
  55. InitFieldValue(ref node, config);
  56. }
  57. catch (Exception e)
  58. {
  59. throw new Exception($"InitFieldValue error, node: {node.Id} {node.Type}", e);
  60. }
  61. return node;
  62. });
  63. }
  64. }
  65. private static void InitFieldValue(ref Node node, NodeProto nodeProto)
  66. {
  67. Type type = Game.EventSystem.Get(DLLType.Model).GetType("Model." + nodeProto.Name);
  68. foreach (var args_item in nodeProto.Args.Dict())
  69. {
  70. FieldInfo fieldInfo = type.GetField(args_item.Key, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  71. if (fieldInfo == null)
  72. {
  73. continue;
  74. }
  75. NewSetValue(ref node, fieldInfo, args_item.Value);
  76. }
  77. }
  78. private static void NewSetValue(ref Node node, FieldInfo field, object value)
  79. {
  80. // unity enum无法序列化,保存的string形式
  81. if (field.FieldType.IsEnum)
  82. {
  83. value = Enum.Parse(field.FieldType, (string) value);
  84. }
  85. if (field.FieldType.IsArray)
  86. {
  87. if (field.FieldType.GetElementType().IsSubclassOf(typeof(UnityEngine.Object)))
  88. {
  89. Array sourceArray = (Array) value;
  90. Array dest = Array.CreateInstance(field.FieldType.GetElementType(), sourceArray.Length);
  91. Array.Copy(sourceArray, dest, dest.Length);
  92. field.SetValue(node, dest);
  93. value = dest;
  94. }
  95. }
  96. field.SetValue(node, value);
  97. }
  98. private Node CreateOneNode(NodeProto proto)
  99. {
  100. if (!this.dictionary.ContainsKey(proto.Name))
  101. {
  102. throw new KeyNotFoundException($"NodeType没有定义该节点: {proto.Name}");
  103. }
  104. return this.dictionary[proto.Name](proto);
  105. }
  106. private Node CreateTreeNode(NodeProto proto)
  107. {
  108. Node node = this.CreateOneNode(proto);
  109. node.EndInit(this.GetParent<Scene>());
  110. if (proto.Children == null)
  111. {
  112. return node;
  113. }
  114. foreach (NodeProto nodeProto in proto.Children)
  115. {
  116. Node childNode = this.CreateTreeNode(nodeProto);
  117. node.AddChild(childNode);
  118. }
  119. return node;
  120. }
  121. public BehaviorTree CreateTree(Scene scene, GameObject treeGo)
  122. {
  123. return this.CreateTree(scene, 0, treeGo);
  124. }
  125. public BehaviorTree CreateTree(Scene scene, long ownerId, GameObject treeGo)
  126. {
  127. try
  128. {
  129. if (treeGo == null)
  130. {
  131. return null;
  132. }
  133. BehaviorTree tree;
  134. if (this.treeCache.TryGetValue(treeGo, out tree))
  135. {
  136. return tree;
  137. }
  138. BehaviorTreeConfig behaviorTreeConfig = treeGo.GetComponent<BehaviorTreeConfig>();
  139. Node node = this.CreateTreeNode(behaviorTreeConfig.RootNodeProto);
  140. tree = new BehaviorTree(scene, ownerId, node) {GameObjectId = treeGo.GetInstanceID()};
  141. if (Define.IsAsync)
  142. {
  143. this.treeCache.Add(treeGo, tree);
  144. }
  145. return tree;
  146. }
  147. catch (Exception e)
  148. {
  149. throw new Exception($"行为树配置错误: {treeGo.name}", e);
  150. }
  151. }
  152. }
  153. }