public virtual bool moveAgent(GOAPAction nextAction) { /* * float dist = Vector3.Distance (transform.position, nextAction.target.transform.position); * if (dist < aggroDist) { * Vector3 moveDirection = player.transform.position - transform.position; * * setSpeed (speed); * * if (initialSpeed < terminalSpeed) { * initialSpeed += acceleration; * } * * Vector3 newPosition = moveDirection * initialSpeed * Time.deltaTime; * transform.position += newPosition; * } * if(dist <= minDist) { * nextAction.setInRange(true); * return true; * } else { * return false; * } */ return(false); }
public virtual bool moveAgent(GOAPAction nextAction) { float dist = Vector3.Distance(transform.position, nextAction.target.transform.position); if (dist < aggroDist) { Vector3 moveDirection = player.transform.position - transform.position; setSpeed(speed); if (initialSpeed < terminalSpeed) { initialSpeed += acceleration; } Vector3 newPosition = moveDirection * initialSpeed * Time.deltaTime; transform.position += newPosition; } if (dist <= minDist) { nextAction.setInRange(true); return(true); } else { return(false); } }
/// <summary> /// Consturctor /// </summary> /// <param name="parent">Parent of the node.</param> /// <param name="cost">Cost of the node.</param> /// <param name="state">The state in the node.</param> /// <param name="action">The action in the node.</param> public Node(Node parent, float cost, HashSet <KeyValuePair <string, object> > state, GOAPAction action) { m_Parent = parent; m_Cost = cost; m_State = state; m_Action = action; }
/** * compares the two nodes for precedence, returns true if node one has higher precedence than node two */ public override bool CompareNodes(AStarNode node1, AStarNode node2) { GOAPAction action1 = GetAction(node1.NodeID); GOAPAction action2 = GetAction(node2.NodeID); return(action1.Precedence < action2.Precedence); }
/// <summary> /// 构建效果地图 /// Builds the actions effects table. /// </summary> public void BuildActionsEffectsTable() { //Go through every effect and add all the actions that have this effect to the effectsTable for (E_GOAPAction i = 0; i < E_GOAPAction.count; i++) { GOAPAction action = Ai.GetAction(i); if (action == null) { continue; } //go through all world effects for (uint j = 0; j < (int)E_PropKey.E_COUNT; j++) { if (action.WorldEffects.IsWSPropertySet((E_PropKey)j)) // if set { if (m_EffectsTable[j] == null) { m_EffectsTable[j] = new List <GOAPAction>(); } m_EffectsTable[j].Add(action); // store it } } } }
public void Plan() { currPlan.Clear(); //first of all clear our current plan //now start making stacks for the planning tree Stack <GOAPStates> goapSimWorldStates = new Stack <GOAPStates>(); //first stack is for the world states Stack <GOAPAction> goapSimActions = new Stack <GOAPAction>(); //second stack will hold the actions Stack <int> goapSimTreeDepth = new Stack <int>(); //third stack will hold the depth of the tree GOAPAction[] agentSimPlans = new GOAPAction[planDepth]; //have a plan that will go as deep as planDepth variable we set above int lowestDepth = int.MaxValue; //set the lowest tree depth to infinity because we dont know the best plan as of yet so we just set the lowest depth to be inf //START INITIALIZING BASE VALUES FOR OUR STACKS goapSimWorldStates.Push(new GOAPStates(worldStates)); //push the present real world state for the agent goapSimTreeDepth.Push(0); //push 0 depth because we just are starting the plan so when initializng we are just at 0 goapSimActions.Push(null); //here we push null because we again we just starting the plan and we have no actions yet but we push null to make sure the agent moves together with the other stacks also action is null @ very start //NOW BEGIN THE PLANNING LOOP, now we will keep planning and find ALL the tree nodes UNTILL we find everything from the present to then finally pop the actual present node from the stack //ONCE we have popped the present node this means we have bascially reached the end and have information on all the nodes while (goapSimWorldStates.Count != 0) { GOAPStates agentCurrentSimState = goapSimWorldStates.Pop(); //now we pop the first world state / node and then we begin going through its children nodes int agentCurrentDepth = goapSimTreeDepth.Pop(); //get the depth for this world state GOAPAction agentCurrentAction = goapSimActions.Pop(); //get the actions that have led us to this current world state agentSimPlans[agentCurrentDepth] = agentCurrentAction; //insert our agents current action in an array so we know what we have gone through //check if i reached the goal or the current depth is larger than the max planned depth. if (agentCurrentSimState.CompareStates(agentGoals[0].agentsFinalGoal) == 0 || agentCurrentDepth >= planDepth) { if (agentCurrentDepth < lowestDepth) { // if the agents current depth is lower than the lowest depth the remove our plan and start a new one. currPlan.Clear(); for (int i = 0; i < agentSimPlans.Length; i++) { if (agentSimPlans[i] != null) { currPlan.Enqueue(agentSimPlans[i]); } } } } else//check all the available actions for the next step { for (int i = 0; i < agentActions.Count; i++) { //check if the required states EXIST in the agents current simulation state //check if the actions outcome states is greater than 0 making sure it is not going to be redundant //making sure there is nothing left out of the required states in the c world state //we do this by checking the current sim world state if it has all the outcomes so if its > 0 something is new / this action is not redundant if (agentCurrentSimState.CompareStates(agentActions[i].requiredStates) == 0 && agentCurrentSimState.CompareStates(agentActions[i].outcomeStates) > 0) { //start by creating a new branch & essentially start a new action GOAPStates newSimState = new GOAPStates(agentCurrentSimState); newSimState.AddUniqueStates(agentActions[i].outcomeStates); goapSimWorldStates.Push(newSimState); goapSimTreeDepth.Push(agentCurrentDepth + 1); goapSimActions.Push(agentActions[i]); } } } } }
public Node(Node parent, float cost, Dictionary <string, int> states, GOAPAction action) { this.parent = parent; this.cost = cost; this.states = new Dictionary <string, int>(states); this.action = action; }
public Node(Node parent, float cost, Dictionary <string, int> allStates, GOAPAction action) { this.parent = parent; this.cost = cost; this.state = new Dictionary <string, int>(allStates);//want this to just be a copy and not point to the dict in the args this.action = action; }
public BrachNode(BrachNode _parent, float _runningCost, HashSet <KeyValuePair <string, object> > _state, GOAPAction _action) { parent = _parent; runningCost = _runningCost; state = _state; action = _action; }
public Node(Node parent, float runningCost, HashSet <KeyValuePair <string, object> > state, GOAPAction action) { this.parent = parent; this.runningCost = runningCost; this.state = state; this.action = action; }
public bool UpdatePlan(WorldState curWS) { if (_actions.Count == 0) { return(false); } GOAPAction curGOAPAction = _actions.Peek(); if (!curGOAPAction.IsValid()) { Clear(); return(false); } if (curGOAPAction.IsFinished) { //curGOAPAction.ApplyEffect(curWS); // 实施效果(其实没必要调用了,因为这时候没有必要设置ws效果了,因为ws的效果没有意义,接着执行下面的action就行) _actions.Dequeue().Release(); if (_actions.Count > 0) { curGOAPAction = _actions.Peek(); curGOAPAction.Activate(); } } else { curGOAPAction.UpdateGOAPAction(); } return(true); }
/// <summary> /// Preforms the action if the agent is in range /// </summary> private void CreatePerformActionState() { prefromActionState = (fsm, gameObj) => { // perform the action if (!HasActionPlan()) { // no actions to perform Debug.Log("<color=red>Done actions</color>"); fsm.PopState(); fsm.PushState(idleState); dataProvider.ActionFinished(); return; } GOAPAction action = currentActions.Peek(); if (action.IsDone()) { // the action is done. Remove it so we can perform the next one currentActions.Dequeue(); } if (HasActionPlan()) { // perform the next action action = currentActions.Peek(); bool inRange = action.RequiresInRange() ? action.IsInRange() : true; if (inRange) { // we are in range, so perform the action bool success = action.Preform(gameObj); if (!success) { // action failed, we need to plan again fsm.PopState(); fsm.PushState(idleState); Debug.LogWarning(gameObj.name + " could not prefrom the action, " + action + ". The agent (" + gameObject.name + ") is now going to abort plan."); dataProvider.PlanAborted(action); } } else { // we need to move there first // push moveTo state fsm.PushState(moveToState); } } else { // no actions left, move to Plan state fsm.PopState(); fsm.PushState(idleState); dataProvider.ActionFinished(); } }; }
public static void Collect(GOAPAction action) { if (action == null) { return; } _buffers[(int)action.Type].Enqueue(action); }
void LateUpdate() { if (currentAction != null && currentAction.running) { if (currentAction.agent.hasPath && currentAction.agent.remainingDistance < 1f) { if (!invoked) { Invoke("CompleteAction", currentAction.duration); invoked = true; } } return; } if (planner == null || actionQueue == null) { planner = new GOAPPlanner(); var sortedGoals = from entry in goals orderby entry.Value descending select entry; foreach (KeyValuePair <SubGoal, int> sg in sortedGoals) { actionQueue = planner.plan(actions, sg.Key.sgoals, null); if (actionQueue != null) { currentGoal = sg.Key; break; } } } if (actionQueue != null && actionQueue.Count == 0) { if (currentGoal.remove) { goals.Remove(currentGoal); } planner = null; } if (actionQueue != null && actionQueue.Count > 0) { currentAction = actionQueue.Dequeue(); if (currentAction.PrePerform()) { if (currentAction.target != null) { currentAction.running = true; currentAction.agent.SetDestination(currentAction.target.transform.position); } } else { actionQueue = null; } } }
public virtual bool MoveAgent(GOAPAction nextAction) { if (PathToTarget == null || !PathToTarget.Finished || PathToTarget.State != PathState.Ready) { if (PathToTarget == null) { PathToTarget = Path.Calculate(Map.Instance.AStarNetwork, transform.position, nextAction.Targets.Select(t => new Vector3I(t)).ToList(), true); } if (PathToTarget != null && PathToTarget.State == PathState.Invalid) { PathToTarget.Dispose(); PathToTarget = null; } return(false); } if (nextAction.IsInRange(_agent)) { return(true); } if (_currentNode == null) { _currentNode = PathToTarget.GetNode(0); if (_currentNode == null) { PathToTarget = null; return(true); } _pathIndex = 0; } PathToTarget.Visualize(Color.red, _pathIndex); var moveDist = MoveSpeed * Time.deltaTime; while (moveDist > 0) { if ((transform.position - _currentNode.Position).magnitude > moveDist) { transform.Translate((_currentNode.Position - transform.position).normalized * moveDist, Space.Self); transform.Find("Scale").LookAt(_currentNode.Position); return(false); } else { moveDist -= (transform.position - _currentNode.Position).magnitude; transform.position = _currentNode.Position; _currentNode = PathToTarget.GetNode(++_pathIndex); if (_currentNode == null) { PathToTarget = null; return(false); } } } return(true); }
private void createPerformActionState() { performActionState = (FiniteStateMachine, gameObj) => { //performs action if (!hasActionPlan()) { //no actions FiniteStateMachine.Pop(); FiniteStateMachine.Push(idleState); dataProvider.actionsFinished(); return; } GOAPAction action = currentActions.Peek(); if (action.isDone()) { //action done currentActions.Dequeue(); } if (hasActionPlan()) { //perform next action action = currentActions.Peek(); bool inRange = action.mustBeInRange() ? action.isInRange() : true; if (inRange) { //in range bool success = action.perform(gameObj); if (!success) { //action failed FiniteStateMachine.Pop(); FiniteStateMachine.Push(idleState); dataProvider.planAborted(action); } } else { //move there first FiniteStateMachine.Push(moveState); } } else { //no actions left FiniteStateMachine.Pop(); FiniteStateMachine.Push(idleState); dataProvider.actionsFinished(); } }; }
private void createPerformActionState() { performActionState = (fsm, gameObj) => { // Perform the action if (!hasActionPlan()) { // No actions to perform fsm.popState(); fsm.pushState(idleState); dataProvider.actionsFinished(); return; } GOAPAction action = currentActions.Peek(); if (action.isDone()) { // The action is done. We can remove it, onto the next one! currentActions.Dequeue(); } if (hasActionPlan()) { // Perform the next action action = currentActions.Peek(); bool inRange = action.requiresInRange() ? action.isInRange() : true; if (inRange) { // We're in range, so perform the action bool success = action.perform(gameObj); if (!success) { // Action failed, we need to plan again fsm.popState(); fsm.pushState(idleState); dataProvider.planAborted(action); } } else { // We need to move to our target first // Let's make the AI move fsm.pushState(moveToTargetState); } } // If all fails, change back to idleState (planning stage) else { fsm.popState(); fsm.pushState(idleState); dataProvider.actionsFinished(); } }; }
//Animation state plays an animation such as shooting, swinging sword. The effect of the animation should be programmed outside of the GOAP system. //The GOAP system only plays animations and moves the agent void animateStateInit() { animateState = (fsm, gameObj) => { GOAPAction action = actionQueue.Peek(); if (action.isDone(this) && actionActivated) { // the action is done. Remove it so we can perform the next one actionActivated = false; actionQueue.Dequeue(); if (actionQueue.Count == 0) { fsm.popState(); fsm.pushState(idleState); } } else { if (action.requiresInRange) { //If an action requires to be in range of a type of object (set by the actions targetTag), we must find one and go to it before playing the animation target = FindClosestTarget(action.targetTag); if (target == null) { //No target. Action failed fsm.popState(); fsm.pushState(idleState); } else { //Only go to the target object if out of range if (Vector3.Distance(target.transform.position, this.transform.position) > action.range) { targetSet = false; fsm.pushState(goToState); } else if (action != currentAction) { //Otherwise activate the action currentAction = action; currentAction.activate(this); actionActivated = true; } } } else if (currentAction != action) { //Activate the current action currentAction = action; currentAction.activate(this); actionActivated = true; } } }; }
private void Start() { creature = GetComponent <Creature>(); //Debug start GOAPAction drink = new GOAPAction(); drink.task = GOAPAction.Task.DRINK; drink.status = GOAPAction.Status.WAITING; QueueTask(drink); StartTask(); //Debug end }
//Create a subset of the actions private HashSet <GOAPAction> actionSubset(HashSet <GOAPAction> actions, GOAPAction removeMe) { HashSet <GOAPAction> subset = new HashSet <GOAPAction>(); foreach (GOAPAction a in actions) { if (!a.Equals(removeMe)) { subset.Add(a); } } return(subset); }
private List <GOAPAction> ActionSubset(List <GOAPAction> usableActions, GOAPAction removeThisAction) { List <GOAPAction> subset = new List <GOAPAction>(); foreach (GOAPAction act in usableActions) { if (!act.Equals(removeThisAction)) { subset.Add(act); } } return(subset); }
private List <GOAPAction> ActionSubset(List <GOAPAction> actions, GOAPAction actionToRemove) { List <GOAPAction> subset = new List <GOAPAction>(); foreach (GOAPAction act in actions) { if (!act.Equals(actionToRemove)) { subset.Add(act); } } return(subset); }
public bool Execute() { curAction = isFinished ? null : m_Actions[curStep]; if (curAction != null) { if (!curAction.CheckPreconditions()) { return(false); } curAction.Activate(); } return(true); }
private void CreatePerformActionState(GOAPComponent aic) { aic.performActionState = (fsm, obj) => { //aic.AnnouncePerformActionState(); if (!aic.HasActionPlan()) { fsm.popState(); fsm.pushState(aic.idleState); aic.ActionsFinished(); return; } GOAPAction action = aic.currentActions.Peek(); if (action.isDone()) { aic.currentActions.Dequeue(); } if (aic.HasActionPlan()) { action = aic.currentActions.Peek(); bool inRange = action.requiresInRange() ? action.isInRange() : true; if (inRange) { bool success = action.perform(obj); if (!success) { fsm.popState(); fsm.pushState(aic.idleState); CreateIdleState(aic); aic.PlanAborted(action); } } else { fsm.pushState(aic.moveToState); } } else { fsm.popState(); fsm.pushState(aic.idleState); aic.ActionsFinished(); } }; }
/// <summary> /// Create the perform action state. /// </summary> private void CreatePerformActionState() { m_PerformActionState = (fsm, gameObject) => { // If the agent has no plan, go to the idle state and say we are doing nothing. if (!HasActionPlan()) { fsm.RemoveState(); fsm.AddState(m_IdleState); m_DataProvider.ActionsFinished(); return; } GOAPAction action = m_CurrentActions.Peek(); if (action.IsDone()) { m_CurrentActions.Dequeue(); } // If the agent has a plan. if (HasActionPlan()) { action = m_CurrentActions.Peek(); // Check if in range of action. bool inRange = action.RequiresInRange() ? action.IsInRange() : true; // If we are in range for the action. if (inRange) { // Check if the agent was able to perform the action. bool success = action.Perform(gameObject); // If not, abort plan and go back to idle. if (!success) { fsm.RemoveState(); fsm.AddState(m_IdleState); m_DataProvider.PlanAborted(action); } } // If not in range, start moving towards target. else { fsm.AddState(m_MoveToState); } } }; }
public GOAPState(GOAPState source, GOAPAction gen = null) { foreach (var elem in source.values) { if (values.ContainsKey(elem.Key)) { values[elem.Key] = elem.Value; } else { values.Add(elem.Key, elem.Value); } } generatingAction = gen; }
public override bool moveAgent(GOAPAction nextAction) { float dist = Vector3.Distance(this.transform.position, nextAction.target.transform.position); if (nextAction.requiesVision) { return(MovementCheck(dist, nextAction)); } else if (!nextAction.requiesVision) { return(MovementCheck(dist, nextAction)); } return(false); }
public override bool moveAgent(GOAPAction nextAction) { float dist = Vector3.Distance(this.transform.position, nextAction.target.transform.position); if (nextAction.requiesVision) { if (dist < config.aggroDist) { var teleporTo = BestPlaceToTeleport(nextAction.transform.transform.position); if (teleporTo != null) { this.transform.position = teleporTo.position; } anim.Play("Move"); anim.SetBool("isWalking", true); agent.destination = nextAction.target.transform.position; agent.isStopped = false; } if (dist <= config.attackDistance) { agent.isStopped = true; nextAction.setInRange(true); return(true); } else { return(false); } } else if (!nextAction.requiesVision) { var teleporTo = BestPlaceToTeleport(nextAction.transform.transform.position); if (teleporTo != null) { this.transform.position = teleporTo.position; } agent.destination = nextAction.target.transform.position; agent.isStopped = false; return(true); } else { anim.Play("Idle"); return(false); } }
void CallTask(GOAPAction a) { switch (a.task) { case GOAPAction.Task.IDLE: Debug.Log("IdleTask"); break; case GOAPAction.Task.DRINK: Debug.Log("DrinkTask"); creature.StartDrinkTask(); break; } taskActive = true; }
public bool moveAgent(GOAPAction nextAction) { // To-do: Change this code to the pathfinding system float step = 1f * Time.deltaTime; gameObject.transform.position = Vector2.MoveTowards(gameObject.transform.position, nextAction.rTarget.transform.position, step); if (gameObject.transform.position.Equals(nextAction.rTarget.transform.position)) { nextAction.setInRange(true); return(true); } else { return(false); } }