diff --git a/Editor/Core/GOAPPlannerProEditor.cs b/Editor/Core/GOAPPlannerProEditor.cs index d59e0c1..7e2e3cb 100644 --- a/Editor/Core/GOAPPlannerProEditor.cs +++ b/Editor/Core/GOAPPlannerProEditor.cs @@ -13,7 +13,7 @@ public class GOAPPlannerProEditor : UnityEditor.Editor private const string IsActiveTooltip = "Whether current planner is active, will be disbled automatically" + " when skipSearchWhenActionRunning is on"; private const string SkilSearchTooltip = "Enabled to skip search plan when already have an action, enable this will need you to set correct precondition" + - "for each action to let it quit by itself"; + " for each action to let it quit by itself"; public override VisualElement CreateInspectorGUI() { var myInspector = new VisualElement(); diff --git a/Editor/Core/GOAPPlannerSnapshotEditorWindow.cs b/Editor/Core/GOAPPlannerSnapshotEditorWindow.cs index 39be8d7..61600c6 100644 --- a/Editor/Core/GOAPPlannerSnapshotEditorWindow.cs +++ b/Editor/Core/GOAPPlannerSnapshotEditorWindow.cs @@ -51,10 +51,10 @@ public class GOAPPlannerSnapshotEditorWindow : EditorWindow private readonly List planeCaches = new List(); private int currentIndex; - private List goalData => planeCaches[currentIndex].goalData; - private List activePlan => planeCaches[currentIndex].activePlan; - private IGoal activeGoal => planeCaches[currentIndex].activeGoal; - private int activeActionIdx => planeCaches[currentIndex].activeActionIdx; + private List GoalData => planeCaches[currentIndex].goalData; + private List ActivePlan => planeCaches[currentIndex].activePlan; + private IGoal ActiveGoal => planeCaches[currentIndex].activeGoal; + private int ActiveActionIdx => planeCaches[currentIndex].activeActionIdx; private class PlanCache { public IGoal activeGoal; @@ -64,7 +64,7 @@ private class PlanCache } public static void Show(IPlanner planner) { - var window = GOAPPlannerSnapshotEditorWindow.GetWindow("GOAP Planner Snapshot"); + var window = GetWindow("GOAP Planner Snapshot"); window.SetUp(planner); window.Show(); } @@ -159,9 +159,9 @@ private void CachePlan(IPlanner planner) planeCaches.Add(new PlanCache { activeGoal = planner.ActivateGoal, - goalData = (planner as IPlanner).GetSortedGoalData(), + goalData = planner.GetSortedGoalData(), activePlan = new List(planner.ActivatePlan), - activeActionIdx = (planner as IPlanner).ActiveActionIndex + activeActionIdx = planner.ActiveActionIndex }); if (planeCaches.Count > 50) planeCaches.RemoveAt(0); } @@ -275,17 +275,17 @@ private void DrawGoalPriorities(int unusedWindowID) GUILayout.Label("\n\n"); GUI.color = runningTint; GUI.backgroundColor = backgroundNodeColor; - for (int i = 0; i < goalData.Count; i++) + for (int i = 0; i < GoalData.Count; i++) { GUI.Box( new Rect( 0, 30f + i * prioritySpacing, - Mathf.Clamp(goalData[i].priority, 0.05f, 1f) * maxPriorityRectWidth, + Mathf.Clamp(GoalData[i].priority, 0.05f, 1f) * maxPriorityRectWidth, priorityRectHeight ), - goalData[i].goalName, - goalData[i].canRun ? goalLabelStyle : disabledGoalLabelStyle + GoalData[i].goalName, + GoalData[i].canRun ? goalLabelStyle : disabledGoalLabelStyle ); } @@ -298,7 +298,7 @@ private void DrawActionNodes(int unusedWindowID) { if (planeCaches.Count == 0) return; int count = 0; - for (int i = 0; i < activePlan.Count; i++) + for (int i = 0; i < ActivePlan.Count; i++) { // Draw link @@ -313,7 +313,7 @@ private void DrawActionNodes(int unusedWindowID) GUI.color = defaultTint; GUI.backgroundColor = backgroundNodeColor; - if (i == activeActionIdx) + if (i == ActiveActionIdx) { GUI.color = runningTint; activeNodeStyle = selectedNodeStyle; @@ -328,7 +328,7 @@ private void DrawActionNodes(int unusedWindowID) "", activeNodeStyle); - actionContent.text = "\nAction\n\n" + activePlan[i].Name; + actionContent.text = "\nAction\n\n" + ActivePlan[i].Name; // Draw task rect GUI.backgroundColor = actionColor; @@ -353,7 +353,7 @@ private void DrawActionNodes(int unusedWindowID) "", selectedNodeStyle); GUI.backgroundColor = goalColor; - goalContent.text = "\nGoal\n\n" + activeGoal.Name; + goalContent.text = "\nGoal\n\n" + ActiveGoal.Name; GUI.Box( GetTaskRect(count), goalContent, @@ -394,12 +394,12 @@ private void DrawLink( float thickness = 4f) { - Vector2 startPos = new Vector2( + Vector2 startPos = new( startGridPos * nodeSpacing.x + nodeSize.x, activePlanHeight + nodeSize.y * .5f ); - Vector2 endPos = new Vector2( + Vector2 endPos = new( endGridPos * nodeSpacing.x, activePlanHeight + nodeSize.y * .5f ); diff --git a/Editor/Node/GOAPActionNode.cs b/Editor/Node/GOAPActionNode.cs index f6d3e7d..13e3b71 100644 --- a/Editor/Node/GOAPActionNode.cs +++ b/Editor/Node/GOAPActionNode.cs @@ -4,19 +4,19 @@ namespace Kurisu.GOAP.Editor { public class GOAPActionNode : GOAPNode { - public GOAPActionNode():base() + public GOAPActionNode() : base() { - label.style.color=Color.black; + label.style.color = Color.black; } - private readonly Label label=new Label(); + private readonly Label label = new(); protected sealed override void OnCleanUp() { titleContainer.Remove(label); } public void SetUp(float cost) { - style.backgroundColor=Color.green; - label.text=$"Cost : {cost}"; + style.backgroundColor = Color.green; + label.text = $"Cost : {cost}"; titleContainer.Add(label); } } diff --git a/Editor/Node/GOAPGoalNode.cs b/Editor/Node/GOAPGoalNode.cs index 3dbf921..4c6ce15 100644 --- a/Editor/Node/GOAPGoalNode.cs +++ b/Editor/Node/GOAPGoalNode.cs @@ -5,20 +5,20 @@ namespace Kurisu.GOAP.Editor { public class GOAPGoalNode : GOAPNode { - public GOAPGoalNode():base() + public GOAPGoalNode() : base() { - label.style.color=Color.black; + label.style.color = Color.black; } - private readonly Label label=new Label(); - + private readonly Label label = new Label(); + protected sealed override void OnCleanUp() { titleContainer.Remove(label); } - public void SetUp(float priority,bool canRun,bool isCurrent) + public void SetUp(float priority, bool canRun, bool isCurrent) { - if(canRun)style.backgroundColor=isCurrent?Color.green:Color.yellow; - label.text=$"Priority : {priority}"; + if (canRun) style.backgroundColor = isCurrent ? Color.green : Color.yellow; + label.text = $"Priority : {priority}"; titleContainer.Add(label); } } diff --git a/Editor/Node/GOAPNode.cs b/Editor/Node/GOAPNode.cs index 0447e0e..1ad96cb 100644 --- a/Editor/Node/GOAPNode.cs +++ b/Editor/Node/GOAPNode.cs @@ -7,15 +7,14 @@ using UnityEngine.UIElements; namespace Kurisu.GOAP.Editor { - public abstract class GOAPNode : UnityEditor.Experimental.GraphView.Node + public abstract class GOAPNode : Node { - private GOAPView bindView; - public GOAPBehavior NodeBehavior {private set;get; } - public string GUID{get;protected set;} - private Type dirtyNodeBehaviorType; + public GOAPBehavior NodeBehavior { private set; get; } + public string GUID { get; protected set; } + private Type dirtyNodeBehaviorType; private readonly VisualElement container; private readonly TextField description; - public string Description=>description.value; + public string Description => description.value; private readonly FieldResolverFactory fieldResolverFactory; public readonly List resolvers = new List(); public Action onSelectAction; @@ -24,13 +23,13 @@ public sealed override void OnSelected() base.OnSelected(); onSelectAction?.Invoke(this); } - + protected GOAPNode() { fieldResolverFactory = FieldResolverFactory.Instance; container = new VisualElement(); description = new TextField(); - GUID=Guid.NewGuid().ToString(); + GUID = Guid.NewGuid().ToString(); Initialize(); } @@ -51,7 +50,7 @@ public void Restore(GOAPBehavior action) NodeBehavior = action; resolvers.ForEach(e => e.Restore(NodeBehavior)); description.value = NodeBehavior.description; - GUID=string.IsNullOrEmpty(action.GUID)?Guid.NewGuid().ToString():action.GUID; + GUID = string.IsNullOrEmpty(action.GUID) ? Guid.NewGuid().ToString() : action.GUID; } private GOAPBehavior ReplaceBehavior() { @@ -62,17 +61,16 @@ public Type GetBehavior() { return dirtyNodeBehaviorType; } - + public void Commit() { ReplaceBehavior(); - resolvers.ForEach( r => r.Commit(NodeBehavior)); - NodeBehavior.description = this.description.value; - NodeBehavior.GUID=this.GUID; + resolvers.ForEach(r => r.Commit(NodeBehavior)); + NodeBehavior.description = description.value; + NodeBehavior.GUID = GUID; } - public void SetBehavior(System.Type nodeBehavior,GOAPView view) + public void SetBehavior(Type nodeBehavior, GOAPView view) { - this.bindView=view; if (dirtyNodeBehaviorType != null) { dirtyNodeBehaviorType = null; @@ -94,13 +92,13 @@ public void SetBehavior(System.Type nodeBehavior,GOAPView view) container.Add(fieldResolver.GetEditorField()); resolvers.Add(fieldResolver); }); - var label=nodeBehavior.GetCustomAttribute(typeof(GOAPLabelAttribute), false) as GOAPLabelAttribute; - title = label?.Title??nodeBehavior.Name; - if(view.Set is IPlanner) + var label = nodeBehavior.GetCustomAttribute(typeof(GOAPLabelAttribute), false) as GOAPLabelAttribute; + title = label?.Title ?? nodeBehavior.Name; + if (view.Set is IPlanner) { - capabilities&=~Capabilities.Copiable; - capabilities &=~Capabilities.Deletable; - capabilities &=~Capabilities.Movable; + capabilities &= ~Capabilities.Copiable; + capabilities &= ~Capabilities.Deletable; + capabilities &= ~Capabilities.Movable; } } @@ -117,7 +115,7 @@ public void CleanUp() { style.backgroundColor = new StyleColor(StyleKeyword.Null); } - protected virtual void OnCleanUp(){} + protected virtual void OnCleanUp() { } } } diff --git a/Editor/Node/NodeResovler.cs b/Editor/Node/NodeResovler.cs index 46c68f6..4a849ae 100644 --- a/Editor/Node/NodeResovler.cs +++ b/Editor/Node/NodeResovler.cs @@ -5,9 +5,9 @@ namespace Kurisu.GOAP.Editor { public class NodeResolver { - private const string NodeStyleSheetPath="AkiGOAP/Node"; + private const string NodeStyleSheetPath = "AkiGOAP/Node"; private StyleSheet styleSheetCache; - public GOAPNode CreateNodeInstance(Type type,GOAPView view) + public GOAPNode CreateNodeInstance(Type type, GOAPView view) { GOAPNode node; if (type.IsSubclassOf(typeof(GOAPGoal))) @@ -17,9 +17,9 @@ public GOAPNode CreateNodeInstance(Type type,GOAPView view) else { node = new GOAPActionNode(); - } - node.SetBehavior(type,view); - if(styleSheetCache==null)styleSheetCache=Resources.Load(NodeStyleSheetPath); + } + node.SetBehavior(type, view); + if (styleSheetCache == null) styleSheetCache = Resources.Load(NodeStyleSheetPath); node.styleSheets.Add(styleSheetCache); return node; } diff --git a/Editor/Window/GOAPEditorWindow.cs b/Editor/Window/GOAPEditorWindow.cs index 7b054e5..e09e87a 100644 --- a/Editor/Window/GOAPEditorWindow.cs +++ b/Editor/Window/GOAPEditorWindow.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; @@ -44,13 +45,27 @@ private VisualElement CreateToolBar(GOAPView graphView) GUI.enabled = !Application.isPlaying; if (GUILayout.Button($"Save", EditorStyles.toolbarButton)) { - var guiContent = new GUIContent(); graphView.Save(); - guiContent.text = $"Update Succeed !"; - ShowNotification(guiContent); + ShowNotification(new GUIContent("Update Succeed !")); } GUI.enabled = true; GUILayout.FlexibleSpace(); + if (GUILayout.Button($"Save To Json", EditorStyles.toolbarButton)) + { + string path = EditorUtility.SaveFilePanel("Select json file save path", Application.dataPath, graphView.Set.Object.name, "json"); + if (!string.IsNullOrEmpty(path)) + { + var template = CreateInstance(); + template.Behaviors.AddRange(graphView.Set.Behaviors); + var serializedData = JsonUtility.ToJson(template); + FileInfo info = new(path); + File.WriteAllText(path, serializedData); + ShowNotification(new GUIContent("Save to json file succeed !")); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + GUIUtility.ExitGUI(); + } GUILayout.EndHorizontal(); } ); diff --git a/Editor/Window/GOAPView.cs b/Editor/Window/GOAPView.cs index 9720a5e..67f2a5a 100644 --- a/Editor/Window/GOAPView.cs +++ b/Editor/Window/GOAPView.cs @@ -27,14 +27,11 @@ public GOAPView(EditorWindow editor, IGOAPSet set) styleSheets.Add(Resources.Load(GraphStyleSheetPath)); SetupZoom(ContentZoomer.DefaultMinScale, ContentZoomer.DefaultMaxScale); Insert(0, new GridBackground()); - var contentDragger = new ContentDragger(); - //鼠标中键移动 contentDragger.activators.Add(new ManipulatorActivationFilter() { button = MouseButton.MiddleMouse, }); - // 添加选框 this.AddManipulator(new SelectionDragger()); this.AddManipulator(new RectangleSelector()); this.AddManipulator(new FreehandSelector()); @@ -73,11 +70,11 @@ public override void BuildContextualMenu(ContextualMenuPopulateEvent evt) base.BuildContextualMenu(evt); var remainTargets = evt.menu.MenuItems().FindAll(e => { - switch (e) + return e switch { - case DropdownMenuAction a: return a.name == "Create Node" || a.name == "Delete"; - default: return false; - } + DropdownMenuAction a => a.name == "Create Node" || a.name == "Delete", + _ => false, + }; }); //Remove needless default actions . evt.menu.MenuItems().Clear(); diff --git a/Example/Scripts/Action/GoToHome.cs b/Example/Scripts/Action/GoToHome.cs index 3209ffb..b2a6fde 100644 --- a/Example/Scripts/Action/GoToHome.cs +++ b/Example/Scripts/Action/GoToHome.cs @@ -22,7 +22,7 @@ public sealed override void OnTick() { agent.NavMeshAgent.SetDestination(agent.Home.position); //You can make a trigger to set state or other method based on unity engine lifetime scope - worldState.SetState("CanRest", Vector3.SqrMagnitude(agent._Transform.position - agent.Home.position) < 1); + worldState.SetState("CanRest", Vector3.SqrMagnitude(agent.Transform.position - agent.Home.position) < 1); } } } diff --git a/Example/Scripts/Action/GoToTent.cs b/Example/Scripts/Action/GoToTent.cs index 1d69f92..af99a75 100644 --- a/Example/Scripts/Action/GoToTent.cs +++ b/Example/Scripts/Action/GoToTent.cs @@ -22,7 +22,7 @@ public sealed override void OnTick() { agent.NavMeshAgent.SetDestination(agent.Tent.position); //You can make a trigger to set state or other method based on unity engine lifetime scope - worldState.SetState("CanRest", Vector3.SqrMagnitude(agent._Transform.position - agent.Tent.position) < 1); + worldState.SetState("CanRest", Vector3.SqrMagnitude(agent.Transform.position - agent.Tent.position) < 1); } } } diff --git a/Example/Scripts/Agent/AgentFactory.cs b/Example/Scripts/Agent/AgentFactory.cs index 508d65e..ce36aef 100644 --- a/Example/Scripts/Agent/AgentFactory.cs +++ b/Example/Scripts/Agent/AgentFactory.cs @@ -24,7 +24,7 @@ private void Awake() var prefab = Instantiate(agentPrefab, GetRandomPosition(), Quaternion.identity); agents[i] = new ExampleAgent(dataSet) { - _Transform = prefab.transform, + Transform = prefab.transform, Home = home, Tent = tent, Player = player diff --git a/Example/Scripts/Agent/ExampleAgent.cs b/Example/Scripts/Agent/ExampleAgent.cs index 065f474..c0971c2 100644 --- a/Example/Scripts/Agent/ExampleAgent.cs +++ b/Example/Scripts/Agent/ExampleAgent.cs @@ -9,34 +9,36 @@ public class ExampleAgent { public ExampleAgent(GOAPSet dataSet) { - this.dataSet=dataSet; + this.dataSet = dataSet; } - public Transform _Transform{get;set;} - public NavMeshAgent NavMeshAgent{get;private set;} + public Transform Transform { get; set; } + public NavMeshAgent NavMeshAgent { get; private set; } private readonly GOAPSet dataSet; - public Transform Player{get;internal set;} - public Transform Home{get;internal set;} - public Transform Tent{get;internal set;} - public int Energy=100; - public void Init() { + public Transform Player { get; internal set; } + public Transform Home { get; internal set; } + public Transform Tent { get; internal set; } + public int Energy = 100; + public void Init() + { //Inject dependency - NavMeshAgent=_Transform.GetComponent(); - var goals=dataSet.GetGoals(); - foreach(var goal in goals.OfType()) + NavMeshAgent = Transform.GetComponent(); + var goals = dataSet.GetGoals(); + foreach (var goal in goals.OfType()) { goal.Inject(this); } - var actions=dataSet.GetActions(); - foreach(var action in actions.OfType()) + var actions = dataSet.GetActions(); + foreach (var action in actions.OfType()) { action.Inject(this); } - var planner=_Transform.GetComponent(); + var planner = Transform.GetComponent(); planner.InjectGoals(goals); planner.InjectActions(actions); } - public void LossEnergy() { - Energy=Mathf.Clamp(Energy-1,0,100); + public void LossEnergy() + { + Energy = Mathf.Clamp(Energy - 1, 0, 100); } } } diff --git a/Example/Scripts/Goal/FollowPlayerGoal.cs b/Example/Scripts/Goal/FollowPlayerGoal.cs index 9d9e623..748d0bf 100644 --- a/Example/Scripts/Goal/FollowPlayerGoal.cs +++ b/Example/Scripts/Goal/FollowPlayerGoal.cs @@ -19,7 +19,7 @@ public sealed override float GetPriority() public sealed override void OnTick() { //If distance * distance is smaller than 4, set 'InDistance' to true - worldState.SetState("InDistance", Vector3.SqrMagnitude(agent._Transform.position - agent.Player.position) < distance); + worldState.SetState("InDistance", Vector3.SqrMagnitude(agent.Transform.position - agent.Player.position) < distance); } } }