public virtual void CopyValues(Action_GS copy) { _agent = copy._agent; _name = copy._name; _cost = copy._cost; _state = copy._state; }
//Constructors ================ public BehaviourSelectMenu_GS(Agent_GS new_target_agent) { //Set the target agent _target_agent = new_target_agent; //Get dropdown slot for behaviour select _behaviour_dropdown_slot = ProTools.GetDropdownSlot(); }
static void ClearAgentPlanning() { //Clear agent planning Agent_GS agent = Selection.activeGameObject.GetComponent <Agent_GS>(); agent.ClearPlanning(); //Clear node editor planning NodeEditor_GS editor = (NodeEditor_GS)EditorWindow.GetWindow(typeof(NodeEditor_GS)); editor.ClearPlanning(); }
//Constructors ================ public Action_GS() { //Set action target agent to null _agent = null; }
//Planning Methods ================ public Stack <ActionNode_GS> GeneratePlan(Agent_GS agent) { //First get the world state states //Current WorldState_GS current_world_state = agent.blackboard.GenerateWorldState(); WorldState_GS current_global_world_state = GlobalBlackboard_GS.blackboard.GenerateWorldState(); current_world_state.MixGoals(current_global_world_state); //Goal //Get current as base world state WorldState_GS goal_world_state = new WorldState_GS(current_world_state); //Apply the goals on the current to get the goal world state goal_world_state.MixGoals(agent.goal_world_state); //Check if the current world state and the goal world state coincide float start_goal_distance = current_world_state.DistanceTo(goal_world_state); if (start_goal_distance < ProTools.MIN_PROPERTY_DISTANCE) { Debug.LogWarning("The current world state coincides with the goal world state: " + goal_world_state.name + " !"); return(new Stack <ActionNode_GS>()); } //Allocate plan start node PlannerNode_GS start_node = new PlannerNode_GS(0, start_goal_distance, new_id_number, 0, current_world_state, null); //Clear open and close dictionaries _open.Clear(); _closed.Clear(); //Reset iterations count _current_iterations = 0; //Add start node to the open list _open.Add(start_node.f, new List <PlannerNode_GS> { start_node }); //Iterate open list till there are no nodes to check while (_open.Count > 0) { //Check and update iterations count if (ProTools.ITERATION_LIMIT < _current_iterations) { Debug.LogWarning("Planning generation for agent: " + agent.name + " failed"); break; } else { _current_iterations += 1; } //Current closed node PlannerNode_GS current_node = CloseNode(); //Check if the resultant world state of the current node is the goal world state if (current_node.resultant_world_state.DistanceTo(goal_world_state) < ProTools.MIN_PROPERTY_DISTANCE) { //Allocate a new queue of actions to store the plan Stack <ActionNode_GS> action_plan = new Stack <ActionNode_GS>(); //Enqueue the goal action action_plan.Push(new ActionNode_GS(current_node.action)); //Iterate goal node "childs" to start node using the parent id while (current_node.parent_id != 0) { //Update current node current_node = _closed[current_node.parent_id]; //Check if the node has an action assigned if (current_node.action != null) { //Enqueue the new current node action_plan.Push(new ActionNode_GS(current_node.action)); } } //Flip the generated queue //Return the generated actions queue return(action_plan); } //Iterate all the avaliable actions for (int k = 0; k < agent.action_nodes_num; k++) { if (agent.action_nodes[k].action == null) { continue; } //Scoped action ActionNode_GS scoped_action = agent.action_nodes[k]; //Check if this action is reachable from the current world state if (scoped_action.ValidateWorldState(current_node.resultant_world_state) == false) { //If the current world state is not valid for this actions we discard it and keep iterating the others continue; } //If this action can be executed in the current world state, action effects are applied in the current world state WorldState_GS new_current_world_state = scoped_action.EffectWorldState(current_node.resultant_world_state); //Check if there is an action in the open list that can also reach the new current world state PlannerNode_GS in_open_node = null; if (IsInOpen(new_current_world_state, out in_open_node) == true) { //In true case check if the new node is better if (current_node.g + scoped_action.action_cost > in_open_node.g) { //The old node is better than this new one continue; } //The new node is better than the old, lets update the node data in_open_node.parent_id = current_node.id; in_open_node.g = current_node.g + scoped_action.action_cost; in_open_node.h = new_current_world_state.DistanceTo(goal_world_state); in_open_node.action = scoped_action; } else { //In false case generate a new open node PlannerNode_GS new_node = new PlannerNode_GS(current_node.g + scoped_action.action_cost, new_current_world_state.DistanceTo(goal_world_state), new_id_number, current_node.id, new_current_world_state, scoped_action); //Add the new node to the open list AddToOpen(new_node); } } } //In no plan found case we return an empty plan return(new Stack <ActionNode_GS>()); }
//Loop Methods ================ public override void OnGUI(Rect rect) { editorWindow.minSize = new Vector2(200.0f, 100.0f); editorWindow.maxSize = new Vector2(200.0f, 100.0f); GUILayout.BeginVertical(); //Menu title GUILayout.BeginHorizontal("Box"); GUILayout.FlexibleSpace(); GUILayout.Label("Action Select", UIConfig_GS.Instance.select_menu_title_style, GUILayout.ExpandWidth(true)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); //Separator EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); //Action select dropdown button ProTools.GenerateButtonDropdownMenu(ref _selected_action_index, ResourcesTool.action_paths, "Select", false, 200.0f, _action_dropdown_slot); if (_selected_action_index != -1) { //Get selected action script value Object script = null; ResourcesTool.action_scripts.TryGetValue(ResourcesTool.action_paths[_selected_action_index], out script); //Allocate a class with the same type of script value Action_GS new_script = ProTools.AllocateClass <Action_GS>(script); //Action node case if (_target_action_node != null) { //Check if the selected action is different to the node action if (_target_action_node.action == null || _target_action_node.action.GetType() != new_script.GetType()) { //Set the class name to the new allocated action new_script.name = ResourcesTool.action_paths[_selected_action_index].PathToName(); //Set the allocated class to the action node _target_action_node.action = new_script; //Set new action agent new_script.agent = _target_action_node.agent; //Set target action node editor action editor _target_action_node_editor.action_editor = new Action_GS_Editor(_target_action_node_editor); //Mark scene dirty EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene()); //Repaint the node editor to update the UI NodeEditor_GS.Instance.Repaint(); } } //Agent idle action case else { Agent_GS target_agent = NodeEditor_GS.Instance.selected_agent; //Check if the selected agent is different to the agent idle action if (target_agent.idle_action == null || target_agent.idle_action.GetType() != new_script.GetType()) { //Set the class name to the new allocated action new_script.name = ResourcesTool.action_paths[_selected_action_index].PathToName(); //Set new action agent new_script.agent = NodeEditor_GS.Instance.selected_agent; //Set the agent idle action target_agent.idle_action = new_script; //Mark scene dirty EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene()); //Repaint the node editor to update the UI NodePlanning_GS.Instance.Repaint(); } } //Close the pop window at the end of the process editorWindow.Close(); } //Action create button if (GUILayout.Button("Create New", GUILayout.ExpandWidth(true))) { //Get mouse current position Vector2 mousePos = Event.current.mousePosition; //Open script creation menu PopupWindow.Show(new Rect(mousePos.x, mousePos.y, 0, 0), new ScriptCreationMenu_GS(ScriptCreationMenu_GS.ScriptCreationType.ScriptC_action, _target_action_node.index)); } GUILayout.EndVertical(); }
private string _id = null; //Window UUID //Constructor ================= public AgentBehaviour_GS_Editor(Agent_GS _agent) { //Set target agent _target_agent = _agent; }