using System; using System.Collections.Generic; using System.Reflection; using UnityEngine; namespace Model { [ObjectEvent] public class BehaviorTreeComponentEvent : ObjectEvent, IAwake, ILoad { public void Awake() { this.Get().Awake(); } public void Load() { this.Get().Load(); } } public class BehaviorTreeComponent : Component { public static BehaviorTreeComponent Instance; private Dictionary> dictionary; private Dictionary treeCache; public void Awake() { Instance = this; this.Load(); } public void Load() { this.dictionary = new Dictionary>(); this.treeCache = new Dictionary(); Type[] types = DllHelper.GetMonoTypes(); foreach (Type type in types) { object[] attrs = type.GetCustomAttributes(typeof(NodeAttribute), false); if (attrs.Length == 0) { continue; } Type classType = type; if (this.dictionary.ContainsKey(type.Name)) { throw new Exception($"已经存在同类节点: {classType.Name}"); } this.dictionary.Add(type.Name, config => { Node node = (Node)Activator.CreateInstance(classType, config); try { InitFieldValue(ref node, config); } catch (Exception e) { throw new Exception($"InitFieldValue error, node: {node.Id} {node.Type}", e); } return node; }); } } private static void InitFieldValue(ref Node node, NodeProto nodeProto) { Type type = ObjectEvents.Instance.Get("Model").GetType("Model." + nodeProto.Name); foreach (var args_item in nodeProto.Args.Dict()) { FieldInfo fieldInfo = type.GetField(args_item.Key, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); if (fieldInfo == null) { continue; } NewSetValue(ref node, fieldInfo, args_item.Value); } } private static void NewSetValue(ref Node node, FieldInfo field, object value) { // unity enum无法序列化,保存的string形式 if (field.FieldType.IsEnum) { value = Enum.Parse(field.FieldType, (string) value); } if (field.FieldType.IsArray) { if (field.FieldType.GetElementType().IsSubclassOf(typeof(UnityEngine.Object))) { Array sourceArray = (Array) value; Array dest = Array.CreateInstance(field.FieldType.GetElementType(), sourceArray.Length); Array.Copy(sourceArray, dest, dest.Length); field.SetValue(node, dest); value = dest; } } field.SetValue(node, value); } private Node CreateOneNode(NodeProto proto) { if (!this.dictionary.ContainsKey(proto.Name)) { throw new KeyNotFoundException($"NodeType没有定义该节点: {proto.Name}"); } return this.dictionary[proto.Name](proto); } private Node CreateTreeNode(NodeProto proto) { Node node = this.CreateOneNode(proto); node.EndInit(this.GetParent()); if (proto.Children == null) { return node; } foreach (NodeProto nodeProto in proto.Children) { Node childNode = this.CreateTreeNode(nodeProto); node.AddChild(childNode); } return node; } public BehaviorTree CreateTree(Scene scene, GameObject treeGo) { return this.CreateTree(scene, 0, treeGo); } public BehaviorTree CreateTree(Scene scene, long ownerId, GameObject treeGo) { try { if (treeGo == null) { return null; } BehaviorTree tree; if (this.treeCache.TryGetValue(treeGo, out tree)) { return tree; } BehaviorTreeConfig behaviorTreeConfig = treeGo.GetComponent(); Node node = this.CreateTreeNode(behaviorTreeConfig.RootNodeProto); tree = new BehaviorTree(scene, ownerId, node) {GameObjectId = treeGo.GetInstanceID()}; if (Define.IsAsync) { this.treeCache.Add(treeGo, tree); } return tree; } catch (Exception e) { throw new Exception($"行为树配置错误: {treeGo.name}", e); } } } }