public void Update() { if (current == AgentState.IDLE) { //Transizione a PLANNING: se l'agente ha un task obiettivo non completato, o non esiste una condizione obiettivo, ma il manager delle azioni è comunque in stato STOP if (agent.goal.methods.Count > 0 && !agent.goal.completed && (Time.frameCount % 60 == 0 || Time.frameCount == 1)) { current = AgentState.PLANNING; } //Transizione a EXECUTING: se il manager delle azioni è in stato EXECUTE else if (agent.actionManager.state == ManagerState.EXECUTE) { current = AgentState.EXECUTING; } else if (agent.actionManager.state == ManagerState.PAUSE) { PrimitiveTask currentTask = (PrimitiveTask)agent.actionManager.currentAction; foreach (CuncurrentTask cuncurrent in currentTask.cuncurrentTasks) { if (!currentTask.CheckCuncurrency(cuncurrent, agent)) { return; } } agent.actionManager.Resume(); } } else if (current == AgentState.PLANNING) { /*In this state, agent plans to goal * Transition to EXECUTING : if agent has a plan towards goal (not empty actions list) * Transizion to IDLE: agent has no plan towards goal (empty actions list)*/ //Generate or fix plan List <Task> tasks = new List <Task>(); //If manager has stopped with INVALID state, fix plan and get a new plan if (agent.actionManager.state == ManagerState.INVALID) { //Climb the hierarchy and get the first valid node CompoundTask validNode = Planner.GetValidNode((PrimitiveTask)agent.actionManager.currentAction, agent.state); tasks.Add(validNode); //Generate first segment of fixed plan, planning from the node found List <PrimitiveTask> firstSegment = Planner.GeneratePlan(tasks, agent); if (firstSegment.Count > 0) { //Get second segment from the current plan, deleting tasks who have node found as father or forefather List <PrimitiveTask> secondSegment = new List <PrimitiveTask>(); foreach (PrimitiveTask task in agent.plan) { if (!task.IsMyForeFather(validNode) && !task.completed) { secondSegment.Add(task); } } //Fix the plan concatenating first segment with second segment agent.plan = firstSegment.Concat(secondSegment).ToList <PrimitiveTask>(); } //No plan.. else { agent.plan = new List <PrimitiveTask>(); //If agent is a member of a group, notify it to the leader, who will stop execution of global plan agent.communicationSystem.sendMessage(new Message(agent.leader, MessageContent.ORDER_FAILURE)); } } //Otherwise generate plan else { tasks.Add(agent.goal); agent.plan = Planner.GeneratePlan(tasks, agent); } if (agent.plan != null) { foreach (IGroundAction action in agent.plan) { agent.actionManager.ScheduleAction(action); } agent.actionManager.NextAction(); current = AgentState.EXECUTING; agent.actionManager.state = ManagerState.EXECUTE; } else { agent.actionManager.state = ManagerState.STOP; current = AgentState.IDLE; } } else if (current == AgentState.EXECUTING) { //Dentro lo stato: esecuzione azione corrente del piano //Transizione a IDLE : se il piano è completato con successo, oppure il manager delle azioni è andato in pausa //Transizione a PLANNING : se il piano non è valido (precondizioni azione non valide) agent.actionManager.RunCurrentAction(); if (agent.actionManager.state == ManagerState.EMPTY) { current = AgentState.IDLE; agent.actionManager.state = ManagerState.STOP; agent.goal.completed = true; } else if (agent.actionManager.state == ManagerState.INVALID) { current = AgentState.PLANNING; } else if (agent.actionManager.state == ManagerState.PAUSE) { current = AgentState.IDLE; } } }
public void InstantiateVariables(Task task, List <Term> variables) { if (task.GetType() == typeof(PrimitiveTask)) { PrimitiveTask pt = (PrimitiveTask)task; foreach (Term variable in variables) { int index = pt.arguments.FindIndex((Term arg) => arg.key == variable.key); if (index >= 0) { pt.arguments[index] = variable; } foreach (Atom pre in pt.preconditions) { index = pre.terms.FindIndex((Term arg) => arg.key == variable.key); if (index >= 0) { pre.terms[index] = variable; } } foreach (Atom eff in pt.effects) { index = eff.terms.FindIndex((Term arg) => arg.key == variable.key); if (index >= 0) { eff.terms[index] = variable; } } } } else if (task.GetType() == typeof(CompoundTask)) { CompoundTask ct = (CompoundTask)task; foreach (Method m in ct.methods) { foreach (Atom pre in m.preconditions) { foreach (Term variable in variables) { int index = pre.terms.FindIndex((Term arg) => arg.key == variable.key); if (index >= 0) { pre.terms[index] = variable; } } } foreach (Task subTask in m.subtasks) { InstantiateVariables(subTask, variables); } } } }
static List <PrimitiveTask> SHOPNoBack(List <Task> tasks, List <PrimitiveTask> plan, string personality, State state, HTNAgent agent) { Task task = tasks [0]; if (task.GetType() == typeof(PrimitiveTask)) { PrimitiveTask pt = (PrimitiveTask)task; PrimitiveTask groundAction = InstantiateAction(pt, state, agent); if (groundAction != null) { plan.Add(groundAction); tasks.Remove(pt); if (tasks.Count > 0) { return(SHOPNoBack(tasks, plan, personality, pt.apply(state), agent)); } } else { return(null); } } else if (task.GetType() == typeof(CompoundTask)) { CompoundTask ct = (CompoundTask)task; List <Method> orderdedMethods = new List <Method>(); switch (agent.methodsOrdering) { case MethodsOrdering.NONE: orderdedMethods = ct.methods; break; case MethodsOrdering.PREF: orderdedMethods = ct.methods.OrderBy(m => m.preference != personality).ToList(); break; case MethodsOrdering.COSTANDPREF: orderdedMethods = ct.methods.OrderBy(m => m.leastCost()).ThenBy(m => m.preference != personality).ToList(); break; } foreach (Method m in orderdedMethods) { if (RuleMatcher.MatchCondition(m.preconditions, state, m.logicalOperator)) { List <Task> tempTasks = new List <Task>(tasks); tempTasks.Remove(task); int j = 0; foreach (Task subtask in m.subtasks) { tempTasks.Insert(0 + j, subtask); j++; } List <PrimitiveTask> tempPlan = SHOPNoBack(tempTasks, plan, personality, state, agent); if (tempPlan != null) { plan.Concat(tempPlan); break; } else { return(null); } } } } return(plan); }
public void plan(GameController.WorldState currentWorldState) { finalPlan = new Stack <PrimitiveTask>(); Stack <PlannerState> decompHistory = new Stack <PlannerState>(); GameController.WorldState WorkingWS = currentWorldState.Copy(); tasksToProcess.Push(new PlayGame()); while (tasksToProcess.Count > 0) { Task CurrentTask = tasksToProcess.Pop(); if (CurrentTask.GetType().IsSubclassOf(typeof(CompoundTask))) { CompoundTask CurrentCompoundTask = (CompoundTask)CurrentTask; Method SatisfiedMethod = CurrentCompoundTask.FindSatisfiedMethod(WorkingWS); if (SatisfiedMethod != null) { //PlannerState currentState = new PlannerState(CurrentCompoundTask, finalPlan, tasksToProcess, SatisfiedMethod); // decompHistory.Push(currentState); SatisfiedMethod.subTasks.Reverse(); foreach (Task t in SatisfiedMethod.subTasks) { tasksToProcess.Push(t); } SatisfiedMethod.subTasks.Reverse(); } else if (decompHistory.Count > 0) { //RestoreToLastDecomposedTask(): PlannerState lastState = decompHistory.Pop(); CompoundTask lastCompoundTask = lastState.currentTask; finalPlan = lastState.finalPlan; tasksToProcess = lastState.tasksToProcess; // Remove the failed method and return CompoundTask to the stack. On the next iteration, it will be checked again for a valid method. lastCompoundTask.InvalidateMethod(lastState.currentMethod); tasksToProcess.Push(lastCompoundTask); } } else//Primitive Task { PrimitiveTask CurrentPrimitiveTask = (PrimitiveTask)CurrentTask; if (CurrentPrimitiveTask.PrimitiveConditionsMet(WorkingWS)) { // CurrentPrimitiveTask.ApplyEffects(this, WorkingWS); // Add this PrimitiveTask to the bottom of the finalPlan Stack <PrimitiveTask> temp = new Stack <PrimitiveTask>(); for (int i = 0; i < finalPlan.Count; i++) { PrimitiveTask nextTask = finalPlan.Pop(); temp.Push(nextTask); } temp.Push(CurrentPrimitiveTask); finalPlan = new Stack <PrimitiveTask>(); for (int i = 0; i < temp.Count; i++) { PrimitiveTask nextTask = temp.Pop(); finalPlan.Push(nextTask); } } else if (decompHistory.Count > 0) { //RestoreToLastDecomposedTask(); PlannerState lastState = decompHistory.Pop(); CompoundTask lastCompoundTask = lastState.currentTask; finalPlan = lastState.finalPlan; tasksToProcess = lastState.tasksToProcess; // Remove the failed method and return CompoundTask to the stack. On the next iteration, it will be checked again for a valid method. lastCompoundTask.InvalidateMethod(lastState.currentMethod); tasksToProcess.Push(lastCompoundTask); } } } }
void OnGUI() { //A line separates HTN Editor from task editor Drawing.DrawLine(new Vector2(302, 0), new Vector2(302, 700), Color.grey, 2.0f, false); /*HTN EDITOR*/ items = new List <HTNEditorItem>(); items.Add(new HTNEditorItem( new Rect(new Vector2(0, 0), new Vector2(100, 30)), goal, itemType.COMPOUND)); DrawCompoundTask(goal, null, new Vector2(10, 0)); //GUI.EndScrollView (); Event currentEvent = Event.current; foreach (HTNEditorItem htnItem in items) { if (currentEvent.type == EventType.MouseDown && currentEvent.button == 0 && htnItem.area.Contains(currentEvent.mousePosition) ) { selected = htnItem; } } /*TASK EDITOR*/ if (selected.item != null) { GUIStyle labelStyle = new GUIStyle(); labelStyle.fontSize = 12; labelStyle.normal.textColor = Color.black; labelStyle.fontStyle = FontStyle.Bold; if (selected.type == itemType.COMPOUND) { int i = 0; CompoundTask selectedCT = (CompoundTask)selected.item; GUI.Label(new Rect(editorPos, itemSize), "Name", labelStyle); selectedCT.name = GUI.TextField(new Rect(new Vector2(editorPos.x + 50, editorPos.y), new Vector2(75, 20)), selectedCT.name); if (selectedCT.Equals(goal)) { GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 100), itemSize), "Goal condition", labelStyle); GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 125), new Vector2(120, 20)), "Logical operator"); string[] operatorOptions = new string[] { "AND", "OR" }; int selectedOperator = Array.IndexOf <string> (operatorOptions, agent.logicalOperator.ToString()); selectedOperator = EditorGUI.Popup(new Rect(new Vector2(editorPos.x + 100, editorPos.y + 125), new Vector2(50, 20)), selectedOperator, operatorOptions); if (selectedOperator == 0) { agent.logicalOperator = LogicalOperator.AND; } else if (selectedOperator == 1) { agent.logicalOperator = LogicalOperator.OR; } if (agent.goalCondition.Count > 0) { for (i = 0; i < agent.goalCondition.Count; i++) { Atom cond = agent.goalCondition[i]; string condLabelName = string.Concat(cond.name, "("); foreach (Term var in cond.terms) { condLabelName = string.Concat(condLabelName, var.key); if (cond.terms.IndexOf(var) < cond.terms.Count - 1) { condLabelName = string.Concat(condLabelName, ","); } } condLabelName = string.Concat(condLabelName, ")"); GUI.Label(new Rect( new Vector2(editorPos.x, editorPos.y + 150 + i * 25), new Vector2(200, 50)), condLabelName); if (GUI.Button(new Rect(new Vector2(editorPos.x + 110, editorPos.y + 150 + i * 25), new Vector2(50, 15)), "Edit")) { ConditionEditorWindow.ShowWindow(agent, cond); } if (GUI.Button(new Rect(new Vector2(editorPos.x + 175, editorPos.y + 150 + i * 25), new Vector2(50, 15)), "Delete")) { agent.goalCondition.Remove(cond); ConditionEditorWindow.GetWindow <ConditionEditorWindow>().Close(); } } } if (GUI.Button(new Rect(new Vector2(editorPos.x, editorPos.y + 150 + i * 25), new Vector2(75, 20)), "Add ")) { Atom cond = new Atom("New Condition"); agent.goalCondition.Add(cond); ConditionEditorWindow.ShowWindow(agent, cond); } } } else if (selected.type == itemType.PRIMITIVE) { PrimitiveTask selectedPT = (PrimitiveTask)selected.item; GUI.Label(new Rect(editorPos, itemSize), "Name", labelStyle); selectedPT.name = GUI.TextField(new Rect(new Vector2(editorPos.x + 50, editorPos.y), new Vector2(75, 20)), selectedPT.name); GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 50), itemSize), "Cost", labelStyle); selectedPT.cost = EditorGUI.FloatField(new Rect(new Vector2(editorPos.x + 50, editorPos.y + 50), new Vector2(75, 20)), selectedPT.cost); GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 90), itemSize), "Arguments", labelStyle); int i = 0; scrollPositionArg = GUI.BeginScrollView(new Rect(new Vector2(editorPos.x, editorPos.y + 120), new Vector2(300, 50)), scrollPositionArg, new Rect(new Vector2(editorPos.x, editorPos.y + 120), new Vector2(275, 50 + selectedPT.arguments.Count * 10)), false, false); if (selectedPT.arguments.Count > 0) { for (i = 0; i < selectedPT.arguments.Count; i++) { //GUILayout.BeginHorizontal(GUILayout.Width(200)); GUI.Label(new Rect( new Vector2(editorPos.x, editorPos.y + 120 + i * 25), itemSize), "Name"); List <string> domVarNamesList = new List <string> (); foreach (Term v in agent.domainVariables) { domVarNamesList.Add(v.key); } varIndex = domVarNamesList.IndexOf(selectedPT.arguments[i].key); if (varIndex == -1) { varIndex = 0; } varIndex = EditorGUI.Popup(new Rect(new Vector2(editorPos.x + 105, editorPos.y + 120 + i * 25), new Vector2(50, 20)), varIndex, domVarNamesList.ToArray()); selectedPT.arguments[i] = agent.domainVariables[varIndex]; if (GUI.Button(new Rect(new Vector2(editorPos.x + 160, editorPos.y + 120 + i * 25), new Vector2(50, 15)), "Delete")) { selectedPT.deleteArgument(selectedPT.arguments[i]); } } } GUI.EndScrollView(); Vector2 AddButtonPos = new Vector2(0, 0); if (selectedPT.arguments.Count == 0) { AddButtonPos = new Vector2(editorPos.x, editorPos.y + 120); } else if (selectedPT.arguments.Count > 0) { AddButtonPos = new Vector2(editorPos.x, editorPos.y + 170); } if (GUI.Button(new Rect(AddButtonPos, new Vector2(75, 20)), "Add")) { foreach (Term argument in agent.domainVariables) { if (!selectedPT.arguments.Contains(argument)) { selectedPT.addArgument(argument); break; } } } i = 0; GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 210 + i * 25), new Vector2(120, 20)), "Preconditions", labelStyle); GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 240), new Vector2(120, 20)), "Logical operator"); string[] operatorOptions = new string[] { "AND", "OR" }; int selectedOperator = Array.IndexOf <string> (operatorOptions, selectedPT.logicalOperator.ToString()); selectedOperator = EditorGUI.Popup(new Rect(new Vector2(editorPos.x + 100, editorPos.y + 240), new Vector2(50, 20)), selectedOperator, operatorOptions); if (selectedOperator == 0) { selectedPT.logicalOperator = LogicalOperator.AND; } else if (selectedOperator == 1) { selectedPT.logicalOperator = LogicalOperator.OR; } scrollPositionPre = GUI.BeginScrollView(new Rect(new Vector2(editorPos.x, editorPos.y + 265), new Vector2(300, 50)), scrollPositionPre, new Rect(new Vector2(editorPos.x, editorPos.y + 265), new Vector2(275, 50 + selectedPT.preconditions.Count * 10)), false, false); if (selectedPT.preconditions.Count > 0) { for (i = 0; i < selectedPT.preconditions.Count; i++) { Atom pre = selectedPT.preconditions[i]; string preLabelName = ""; if (pre.sign == false) { preLabelName = string.Concat("NOT(", pre.name, "("); } else if (pre.sign == true) { preLabelName = string.Concat(pre.name, "("); } foreach (Term var in pre.terms) { preLabelName = string.Concat(preLabelName, var.key); if (pre.terms.IndexOf(var) < pre.terms.Count - 1) { preLabelName = string.Concat(preLabelName, ","); } } if (pre.sign == true) { preLabelName = string.Concat(preLabelName, ")"); } else if (pre.sign == false) { preLabelName = string.Concat(preLabelName, "))"); } GUI.Label(new Rect( new Vector2(editorPos.x, editorPos.y + 265 + i * 25), new Vector2(200, 50)), preLabelName); if (GUI.Button(new Rect(new Vector2(editorPos.x + 110, editorPos.y + 265 + i * 25), new Vector2(50, 15)), "Edit")) { ConditionEditorWindow.ShowWindow(agent, pre); } if (GUI.Button(new Rect(new Vector2(editorPos.x + 175, editorPos.y + 265 + i * 25), new Vector2(50, 15)), "Delete")) { selectedPT.deletePrecondition(pre); ConditionEditorWindow.GetWindow <ConditionEditorWindow>().Close(); } } } GUI.EndScrollView(); if (selectedPT.preconditions.Count == 0) { AddButtonPos = new Vector2(editorPos.x, editorPos.y + 275); } else if (selectedPT.preconditions.Count > 0) { AddButtonPos = new Vector2(editorPos.x, editorPos.y + 315); } if (GUI.Button(new Rect(AddButtonPos, new Vector2(75, 20)), "Add ")) { Atom pre = new Atom("New Condition"); selectedPT.addPrecondition(pre); ConditionEditorWindow.ShowWindow(agent, pre); } i = 0; GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 350 + i * 25), new Vector2(120, 20)), "Concurrent tasks", labelStyle); scrollPositionCunc = GUI.BeginScrollView(new Rect(new Vector2(editorPos.x, editorPos.y + 375), new Vector2(350, 75)), scrollPositionCunc, new Rect(new Vector2(editorPos.x, editorPos.y + 375), new Vector2(325, 75 + selectedPT.cuncurrentTasks.Count * 10)), false, false); for (i = 0; i < selectedPT.cuncurrentTasks.Count; i++) { CuncurrentTask cuncurrent = selectedPT.cuncurrentTasks[i]; string[] options = new string[] { "True", "False" }; int selectedIndex = 0; if (cuncurrent.sign == true) { selectedIndex = 0; } else if (cuncurrent.sign == false) { selectedIndex = 1; } selectedIndex = EditorGUI.Popup(new Rect(new Vector2(editorPos.x, editorPos.y + 375 + i * 25), new Vector2(75, 20)), selectedIndex, options); if (selectedIndex == 0) { cuncurrent.sign = true; } else if (selectedIndex == 1) { cuncurrent.sign = false; } cuncurrent.task = GUI.TextField(new Rect(new Vector2(editorPos.x + 100, editorPos.y + 375 + i * 25), new Vector2(75, 20)), cuncurrent.task); selectedPT.cuncurrentTasks[i] = cuncurrent; int selectedVar = agent.domainVariables.IndexOf(agent.domainVariables.Find((Term t) => t.key == cuncurrent.agentVarName)); if (selectedVar == -1) { selectedVar = 0; } List <string> variablesNames = new List <string> (); foreach (Term var in agent.domainVariables) { variablesNames.Add(var.key); } selectedVar = EditorGUI.Popup(new Rect(new Vector2(editorPos.x + 200, editorPos.y + 375 + i * 25), new Vector2(50, 20)), selectedVar, variablesNames.ToArray()); cuncurrent.agentVarName = agent.domainVariables [selectedVar].key; if (GUI.Button(new Rect(new Vector2(editorPos.x + 275, editorPos.y + 375 + i * 25), new Vector2(45, 15)), "Delete")) { selectedPT.cuncurrentTasks.Remove(selectedPT.cuncurrentTasks[i]); ConditionEditorWindow.GetWindow <ConditionEditorWindow>().Close(); } } GUI.EndScrollView(); if (selectedPT.cuncurrentTasks.Count == 0) { AddButtonPos = new Vector2(editorPos.x, editorPos.y + 375); } else if (selectedPT.cuncurrentTasks.Count > 0) { AddButtonPos = new Vector2(editorPos.x, editorPos.y + 425); } if (GUI.Button(new Rect(AddButtonPos, new Vector2(75, 20)), "Add")) { selectedPT.cuncurrentTasks.Add(new CuncurrentTask(" ", false, agent.domainVariables[0].key)); } i = 0; GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 475 + i * 25), new Vector2(120, 20)), "Effects", labelStyle); scrollPositionEff = GUI.BeginScrollView(new Rect(new Vector2(editorPos.x, editorPos.y + 500), new Vector2(300, 50)), scrollPositionEff, new Rect(new Vector2(editorPos.x, editorPos.y + 475), new Vector2(275, 50 + selectedPT.effects.Count * 10)), false, false); if (selectedPT.effects.Count > 0) { for (i = 0; i < selectedPT.effects.Count; i++) { Atom eff = selectedPT.effects[i]; string effLabelName = ""; if (eff.sign == false) { effLabelName = string.Concat("NOT(", eff.name, "("); } else if (eff.sign == true) { effLabelName = string.Concat(eff.name, "("); } foreach (Term var in eff.terms) { effLabelName = string.Concat(effLabelName, var.key); if (eff.terms.IndexOf(var) < eff.terms.Count - 1) { effLabelName = string.Concat(effLabelName, ","); } } if (eff.sign == true) { effLabelName = string.Concat(effLabelName, ")"); } else if (eff.sign == false) { effLabelName = string.Concat(effLabelName, "))"); } GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 475 + i * 25), new Vector2(200, 50)), effLabelName); if (GUI.Button(new Rect(new Vector2(editorPos.x + 110, editorPos.y + 475 + i * 25), new Vector2(45, 15)), "Edit")) { ConditionEditorWindow.ShowWindow(agent, eff); } if (GUI.Button(new Rect(new Vector2(editorPos.x + 175, editorPos.y + 475 + i * 25), new Vector2(45, 15)), "Delete")) { selectedPT.deleteEffect(eff); ConditionEditorWindow.GetWindow <ConditionEditorWindow>().Close(); } } } GUI.EndScrollView(); if (selectedPT.effects.Count == 0) { AddButtonPos = new Vector2(editorPos.x, editorPos.y + 500); } else if (selectedPT.effects.Count > 0) { AddButtonPos = new Vector2(editorPos.x, editorPos.y + 550); } if (GUI.Button(new Rect(AddButtonPos, new Vector2(75, 20)), "Add")) { Atom eff = new Atom("New Effect"); selectedPT.addEffect(eff); ConditionEditorWindow.ShowWindow(agent, eff); } GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 600), new Vector2(120, 20)), "Ground Action", labelStyle); string[] actionsOptions = { "Move", "Animate", "Custom" }; if (selectedPT.actionType == ActionTypes.MOVEMENT) { actionIndex = 0; } else if (selectedPT.actionType == ActionTypes.ANIMATION) { actionIndex = 1; } else if (selectedPT.actionType == ActionTypes.CUSTOM) { actionIndex = 2; } //if (GUI.Button (new Rect(new Vector2(editorPos.x, editorPos.y + 500), new Vector2(200,20)),"Edit Action")); actionIndex = EditorGUI.Popup(new Rect(new Vector2(editorPos.x, editorPos.y + 625), new Vector2(100, 20)), actionIndex, actionsOptions); /*if (selectedPT.groundData == null) * selectedPT.groundData = new GroundData();*/ if (actionIndex == 0) { selectedPT.actionType = ActionTypes.MOVEMENT; GUI.Label(new Rect(new Vector2(editorPos.x + 110, editorPos.y + 625), new Vector2(100, 20)), "Speed"); selectedPT.groundData.speed = EditorGUI.FloatField(new Rect(new Vector2(editorPos.x + 160, editorPos.y + 625), new Vector2(50, 20)), selectedPT.groundData.speed); GUI.Label(new Rect(new Vector2(editorPos.x + 220, editorPos.y + 625), new Vector2(100, 20)), "Radius"); selectedPT.groundData.radius = EditorGUI.FloatField(new Rect(new Vector2(editorPos.x + 270, editorPos.y + 625), new Vector2(50, 20)), selectedPT.groundData.radius); if (agent.gameObject.GetComponent <Animator>() != null) { GUI.Label(new Rect(new Vector2(editorPos.x + 110, editorPos.y + 650), new Vector2(100, 20)), "Animation "); selectedPT.groundData.animationState = GUI.TextField(new Rect(new Vector2(editorPos.x + 180, editorPos.y + 650), new Vector2(50, 20)), selectedPT.groundData.animationState); } } else if (actionIndex == 1) { selectedPT.actionType = ActionTypes.ANIMATION; if (agent.gameObject.GetComponent <Animator>() != null) { GUI.Label(new Rect(new Vector2(editorPos.x + 110, editorPos.y + 625), new Vector2(100, 20)), "State"); selectedPT.groundData.animationState = GUI.TextField(new Rect(new Vector2(editorPos.x + 150, editorPos.y + 625), new Vector2(75, 20)), selectedPT.groundData.animationState); } } else if (actionIndex == 2) { selectedPT.actionType = ActionTypes.CUSTOM; selectedPT.groundData.name = GUI.TextField(new Rect(new Vector2(editorPos.x + 110, editorPos.y + 625), new Vector2(75, 20)), selectedPT.groundData.name.ToString()); if (GUI.Button(new Rect(new Vector2(editorPos.x + 200, editorPos.y + 625), new Vector2(100, 20)), "Create/Open")) { if (!File.Exists("Assets/Actions/" + (string)selectedPT.groundData.name + ".cs")) { using (var stream = new StreamWriter("Assets/Actions/" + (string)selectedPT.groundData.name + ".cs")) { stream.Write( @"using UnityEngine; using System; using System.Collections; public class " + (string)selectedPT.groundData.name + @": PrimitiveTask, IGroundAction { GameObject agentObj; public " + (string)selectedPT.groundData.name + @"(HTNAgent a, string n){ name = n; agentObj = a.gameObject; } public string Name{ get{return name;} set {name = value;} } //This starts agent's action execution public void Start(ActionManager manager, State state){ //Monitor precondition validity in current state: if not valid, notify to manager if (preconditions.Count > 0 && !RuleMatcher.MatchCondition (preconditions, state,logicalOperator)) manager.NotValid (); else { foreach (CuncurrentTask cuncurrent in cuncurrentTasks) if (!CheckCuncurrency (cuncurrent,agentObj.GetComponent<HTNAgent>())){ manager.Suspend (); return; } //Add custom code } } //Runs at every frame during action's execution public void Update(ActionManager manager, State state){ //Monitor preconditions validity in current state: if not valid, notify to manager if (preconditions.Count > 0 && !RuleMatcher.MatchCondition (preconditions, state,logicalOperator)) manager.NotValid (); else { foreach (CuncurrentTask cuncurrent in cuncurrentTasks) if (!CheckCuncurrency (cuncurrent,agentObj.GetComponent<HTNAgent>())){ manager.Suspend (); return; } //Add custom code } } public void OnComplete(ActionManager manager, State state){ //Add custom code //Flag as completed completed = true; //Apply effects foreach (Atom atom in effects){ Atom fact = new Atom(atom.name,atom.sign); foreach (Term var in atom.terms) fact.addTerm(new Term(var.value)); Atom existingFact = state.Contains(fact); if (state.Contains(fact) == null) state.addFact(fact); else existingFact.sign = fact.sign; } //Call next action manager.NextAction (); } }"); stream.Close(); } } UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal("Assets/Actions/" + (string)selectedPT.groundData.name + ".cs", 1); } } } else if (selected.type == itemType.METHOD) { Method selectedM = (Method)selected.item; GUI.Label(new Rect(editorPos, itemSize), "Name", labelStyle); selectedM.name = GUI.TextField(new Rect(new Vector2(editorPos.x + 50, editorPos.y), new Vector2(75, 20)), selectedM.name); if (AtomListWindow.atomNames.list.Count > 0) { GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 75), itemSize), "Preference", labelStyle); string[] options = new string[PersonalityEditorWindow.personalities.list.Count + 2]; options [0] = "none"; PersonalityEditorWindow.personalities.list.CopyTo(options, 1); persIndex = new List <string>(options).IndexOf(selectedM.preference); persIndex = EditorGUI.Popup(new Rect(new Vector2(editorPos.x + 100, editorPos.y + 75), itemSize), persIndex, options); selectedM.preference = options[persIndex]; } GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 125), new Vector2(120, 20)), "Preconditions", labelStyle); GUI.Label(new Rect(new Vector2(editorPos.x, editorPos.y + 150), new Vector2(120, 20)), "Logical operator"); string[] operatorOptions = new string[] { "AND", "OR" }; int selectedOperator = Array.IndexOf <string> (operatorOptions, selectedM.logicalOperator.ToString()); selectedOperator = EditorGUI.Popup(new Rect(new Vector2(editorPos.x + 100, editorPos.y + 150), new Vector2(50, 20)), selectedOperator, operatorOptions); if (selectedOperator == 0) { selectedM.logicalOperator = LogicalOperator.AND; } else if (selectedOperator == 1) { selectedM.logicalOperator = LogicalOperator.OR; } scrollPositionMethoPre = GUI.BeginScrollView(new Rect(new Vector2(editorPos.x, editorPos.y + 175), new Vector2(300, 100)), scrollPositionMethoPre, new Rect(new Vector2(editorPos.x, editorPos.y + 175), new Vector2(275, 100 + selectedM.preconditions.Count * 25)), false, false); int i = 0; if (selectedM.preconditions.Count > 0) { for (i = 0; i < selectedM.preconditions.Count; i++) { Atom pre = selectedM.preconditions[i]; string preLabelName = ""; if (pre.sign == false) { preLabelName = string.Concat("NOT(", pre.name, "("); } else if (pre.sign == true) { preLabelName = string.Concat(pre.name, "("); } foreach (Term var in pre.terms) { preLabelName = string.Concat(preLabelName, var.key); if (pre.terms.IndexOf(var) < pre.terms.Count - 1) { preLabelName = string.Concat(preLabelName, ","); } } if (pre.sign == true) { preLabelName = string.Concat(preLabelName, ")"); } else if (pre.sign == false) { preLabelName = string.Concat(preLabelName, "))"); } GUI.Label(new Rect( new Vector2(editorPos.x, editorPos.y + 200 + i * 25), new Vector2(200, 50)), preLabelName); if (GUI.Button(new Rect(new Vector2(editorPos.x + 110, editorPos.y + 200 + i * 25), new Vector2(45, 15)), "Edit")) { ConditionEditorWindow.ShowWindow(agent, pre); } if (GUI.Button(new Rect(new Vector2(editorPos.x + 175, editorPos.y + 200 + i * 25), new Vector2(45, 15)), "Delete")) { selectedM.deletePrecondition(pre); ConditionEditorWindow.GetWindow <ConditionEditorWindow>().Close(); } } } GUI.EndScrollView(); Vector2 AddButtonPos = new Vector2(0, 0); if (selectedM.preconditions.Count == 0) { AddButtonPos = new Vector2(editorPos.x, editorPos.y + 175); } else if (selectedM.preconditions.Count > 0) { AddButtonPos = new Vector2(editorPos.x, editorPos.y + 275); } if (GUI.Button(new Rect(AddButtonPos, new Vector2(75, 20)), "Add ")) { Atom pre = new Atom("New Condition"); selectedM.addPrecondition(pre); ConditionEditorWindow.ShowWindow(agent, pre); } } } }
//----------------------------------------------------------------------------------------------- private static void ParseEffectForPrimitiveTask(XmlNode effectNode, PrimitiveTask task) { EffectProperty effect = ParseEffectFromNode(effectNode); task.AddEffect(effect); }
//----------------------------------------------------------------------------------------------- private static void ParsePreconditionForPrimitiveTask(XmlNode preconditionNode, PrimitiveTask task) { PreconditionProperty precondition = ParsePreconditionFromNode(preconditionNode); task.AddPrecondition(precondition); }