BehaviorTreeComponent.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using Base;
  5. using UnityEngine;
  6. namespace Model
  7. {
  8. [EntityEvent(EntityEventId.BehaviorTreeComponent)]
  9. public class BehaviorTreeComponent : Component
  10. {
  11. private Dictionary<string, Func<NodeProto, Node>> dictionary;
  12. private Dictionary<GameObject, BehaviorTree> treeCache;
  13. public void Awake()
  14. {
  15. this.Load();
  16. }
  17. public void Load()
  18. {
  19. this.dictionary = new Dictionary<string, Func<NodeProto, Node>>();
  20. this.treeCache = new Dictionary<GameObject, BehaviorTree>();
  21. Type[] types = DllHelper.GetMonoTypes();
  22. foreach (Type type in types)
  23. {
  24. object[] attrs = type.GetCustomAttributes(typeof(NodeAttribute), false);
  25. if (attrs.Length == 0)
  26. {
  27. continue;
  28. }
  29. Type classType = type;
  30. if (this.dictionary.ContainsKey(type.Name))
  31. {
  32. throw new GameException($"已经存在同类节点: {classType.Name}");
  33. }
  34. this.dictionary.Add(type.Name, config =>
  35. {
  36. Node node = (Node)Activator.CreateInstance(classType, config);
  37. try
  38. {
  39. InitFieldValue(ref node, config);
  40. }
  41. catch (Exception e)
  42. {
  43. throw new GameException($"InitFieldValue error, node: {node.Id} {node.Type}", e);
  44. }
  45. return node;
  46. });
  47. }
  48. }
  49. private static void InitFieldValue(ref Node node, NodeProto nodeProto)
  50. {
  51. Type type = ObjectEvents.Instance.GetAssembly("Model").GetType("Model." + nodeProto.Name);
  52. foreach (var args_item in nodeProto.Args.Dict())
  53. {
  54. FieldInfo fieldInfo = type.GetField(args_item.Key, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  55. if (fieldInfo == null)
  56. {
  57. continue;
  58. }
  59. NewSetValue(ref node, fieldInfo, args_item.Value);
  60. }
  61. }
  62. private static void NewSetValue(ref Node node, FieldInfo field, object value)
  63. {
  64. // unity enum无法序列化,保存的string形式
  65. if (field.FieldType.IsEnum)
  66. {
  67. value = Enum.Parse(field.FieldType, (string) value);
  68. }
  69. field.SetValue(node, value);
  70. }
  71. private Node CreateOneNode(NodeProto proto)
  72. {
  73. if (!this.dictionary.ContainsKey(proto.Name))
  74. {
  75. throw new KeyNotFoundException($"NodeType没有定义该节点: {proto.Name}");
  76. }
  77. return this.dictionary[proto.Name](proto);
  78. }
  79. private Node CreateTreeNode(NodeProto proto)
  80. {
  81. Node node = this.CreateOneNode(proto);
  82. node.EndInit(this.GetOwner<Scene>());
  83. if (proto.Children == null)
  84. {
  85. return node;
  86. }
  87. foreach (NodeProto nodeProto in proto.Children)
  88. {
  89. Node childNode = this.CreateTreeNode(nodeProto);
  90. node.AddChild(childNode);
  91. }
  92. return node;
  93. }
  94. public BehaviorTree CreateTree(Scene scene, GameObject treeGo)
  95. {
  96. try
  97. {
  98. BehaviorTree tree;
  99. if (this.treeCache.TryGetValue(treeGo, out tree))
  100. {
  101. return tree;
  102. }
  103. BehaviorTreeConfig behaviorTreeConfig = treeGo.GetComponent<BehaviorTreeConfig>();
  104. Node node = this.CreateTreeNode(behaviorTreeConfig.RootNodeProto);
  105. tree = new BehaviorTree(scene, node);
  106. if (Define.LoadResourceType == LoadResourceType.Async)
  107. {
  108. this.treeCache.Add(treeGo, tree);
  109. }
  110. return tree;
  111. }
  112. catch (Exception e)
  113. {
  114. throw new ConfigException($"行为树配置错误: {treeGo.name}", e);
  115. }
  116. }
  117. }
  118. }