public void Init(BehaviourTree tree) { if (!IsInstance) { Debug.LogError("尝试初始化未实例化的结点: " + name); return; } Tree = tree; foreach (var field in GetType().GetFields(ZetanUtility.CommonBindingFlags).Where(field => field.FieldType.IsSubclassOf(typeof(SharedVariable)))) { var hideAttr = field.GetCustomAttribute <HideIf_BTAttribute>(); if (hideAttr != null && ZetanUtility.TryGetMemberValue(hideAttr.path, this, out var value, out _) && Equals(value, hideAttr.value)) { continue; } SharedVariable variable = field.GetValue(this) as SharedVariable; //if (variable.isShared) field.SetValue(this, this.owner.GetVariable(variable.name)); //else if (variable.isGlobal) field.SetValue(this, BehaviourManager.Instance.GetVariable(variable.name)); if (variable.isShared) { variable.Link(Tree.GetVariable(variable.name)); } else if (variable.isGlobal) { variable.Link(BehaviourManager.Instance.GetVariable(variable.name)); } } Shortcut = new NodeShortcut(Tree.Executor); OnAwake(); #if false void TryLinkSharedVariable(object onwer, FieldInfo field) { if (field.FieldType.IsSubclassOf(typeof(SharedVariable))) { SharedVariable variable = field.GetValue(onwer) as SharedVariable; field.SetValue(this, this.owner.GetVariable(variable.name)); } else if (field.FieldType.IsArray)//因为Unity只能显示数组和列表,只对这两种特殊情况特殊处理 { var array = field.GetValue(owner) as SharedVariable[]; if (array.Length < 1) { return; } bool typeMatch = false; var eType = array[0].GetType(); var fieldInfos = eType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); if (eType.IsSubclassOf(typeof(SharedVariable))) { typeMatch = true; } for (int i = 0; i < array.Length; i++) { if (typeMatch) { array[i] = this.owner.GetVariable(array[i].name); } else { foreach (var _field in fieldInfos) { TryLinkSharedVariable(array[i], _field); } } } } else if (typeof(IList).IsAssignableFrom(field.FieldType)) { var list = field.GetValue(owner) as IList; if (list.Count < 1) { return; } bool typeMatch = false; var eType = list[0].GetType(); var fieldInfos = eType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); if (eType.IsSubclassOf(typeof(SharedVariable))) { typeMatch = true; } for (int i = 0; i < list.Count; i++) { if (typeMatch) { list[i] = this.owner.GetVariable((list[i] as SharedVariable).name); } else { foreach (var _field in fieldInfos) { TryLinkSharedVariable(list[i], _field); } } } } } #endif }
public void InspectNode(BehaviourTree tree, NodeEditor node) { Clear(); if (serializedObject != null) { serializedObject.Dispose(); } this.tree = tree; if (!tree.IsInstance) { global = ZetanUtility.Editor.LoadAsset <GlobalVariables>(); } else { global = BehaviourManager.Instance.GlobalVariables; } nodeEditor = node; if (tree && nodeEditor != null && nodeEditor.node) { serializedObject = new SerializedObject(tree); SerializedProperty nodes = serializedObject.FindProperty("nodes"); IMGUIContainer container = new IMGUIContainer(() => { if (tree && nodeEditor != null && nodeEditor.node) { serializedObject.UpdateIfRequiredOrScript(); EditorGUI.BeginChangeCheck(); EditorGUILayout.LabelField($"[结点名称]\t{nodeEditor.node.name}"); EditorGUILayout.LabelField($"[优先级]\t{nodeEditor.node.priority}"); var nType = nodeEditor.node.GetType(); var fields = new HashSet <string>(nType.GetFields(ZetanUtility.CommonBindingFlags).Select(f => f.Name)); var fieldsMap = new HashSet <string>(); using (SerializedProperty property = nodes.GetArrayElementAtIndex(tree.Nodes.IndexOf(nodeEditor.node))) { using var end = property.GetEndProperty(); property.Next(true); while (property.NextVisible(false) && !SerializedProperty.EqualContents(property, end)) { string field = property.name; if (field == "name" || field == "priority" || field == "child" || field == "children" || field == "start" || field == "isRuntime" || field == "isShared" || field == "isGlobal") { continue; } if (fields.Contains(field)) { if (fieldsMap.Contains(field)) { break; } fieldsMap.Add(field); var fInfo = nType.GetField(field, ZetanUtility.CommonBindingFlags); DrawProperty(property, fInfo); } } } if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } } }); Add(container); } }
public override void OnInspectorGUI() { if (target is RuntimeBehaviourExecutor exe) { if (PrefabUtility.IsPartOfAnyPrefab(exe)) { EditorGUILayout.HelpBox("不能在预制件使用RuntimeBehaviourExecutor", MessageType.Error); return; } else { EditorGUILayout.HelpBox("只在本场景生效,若要制作预制件,请使用BehaviourExecutor", MessageType.Info); } } serializedObject.UpdateIfRequiredOrScript(); EditorGUI.BeginChangeCheck(); var hasTreeBef = behaviour.objectReferenceValue; if (target is not RuntimeBehaviourExecutor) { bool shouldDisable = Application.isPlaying && !PrefabUtility.IsPartOfAnyPrefab(target); EditorGUI.BeginDisabledGroup(shouldDisable); if (shouldDisable) { EditorGUILayout.PropertyField(behaviour, new GUIContent("行为树")); } else { treeDrawer.DoLayoutDraw(); } EditorGUI.EndDisabledGroup(); } if (behaviour.objectReferenceValue != hasTreeBef) { InitTree(); } if (behaviour.objectReferenceValue) { if (GUILayout.Button("编辑")) { BehaviourTreeEditor.CreateWindow(target as BehaviourExecutor); } serializedTree.UpdateIfRequiredOrScript(); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(serializedTree.FindProperty("_name")); EditorGUILayout.PropertyField(serializedTree.FindProperty("description")); if (EditorGUI.EndChangeCheck()) { serializedTree.ApplyModifiedProperties(); } } else { if (GUILayout.Button("新建")) { BehaviourTree tree = ZetanUtility.Editor.SaveFilePanel(CreateInstance <BehaviourTree>, "new behaviour tree"); if (tree) { behaviour.objectReferenceValue = tree; InitTree(); treeDrawer = new ObjectSelectionDrawer <BehaviourTree>(behaviour, string.Empty, string.Empty, "行为树"); EditorApplication.delayCall += delegate { BehaviourTreeEditor.CreateWindow(target as BehaviourExecutor); }; } } } EditorGUILayout.PropertyField(frequency, new GUIContent("执行频率")); if (frequency.enumValueIndex == (int)BehaviourExecutor.Frequency.FixedTime) { EditorGUILayout.PropertyField(interval, new GUIContent("间隔(秒)")); } EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(startOnStart, new GUIContent("开始时执行")); EditorGUILayout.PropertyField(restartOnComplete, new GUIContent("完成时重启")); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(resetOnRestart, new GUIContent("重启时重置")); EditorGUILayout.PropertyField(gizmos, new GUIContent("显示Gizmos")); EditorGUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } if (behaviour.objectReferenceValue) { serializedTree.UpdateIfRequiredOrScript(); showList.target = EditorGUILayout.Foldout(serializedVariables.isExpanded, "行为树共享变量", true); if (EditorGUILayout.BeginFadeGroup(showList.faded)) { variableList.DoLayoutList(); } EditorGUILayout.EndFadeGroup(); if (target is not RuntimeBehaviourExecutor && !Application.isPlaying && !ZetanUtility.IsPrefab((target as BehaviourExecutor).gameObject)) { showPreset.target = EditorGUILayout.Foldout(presetVariables.isExpanded, "变量预设列表", true); if (EditorGUILayout.BeginFadeGroup(showPreset.faded)) { presetVariableList.DoLayoutList(); } EditorGUILayout.EndFadeGroup(); } serializedTree.ApplyModifiedProperties(); } }