protected virtual void OnDisable() { if (reGoapNode != null) { reGoapNode.action.Exit(); reGoapNode = null; reGoapNodeList.Clear(); } }
public ReGoapNode(IGoapPlanner planner, ReGoapState newGoal, ReGoapNode parent, IReGoapAction action) { this.planner = planner; this.parent = parent; this.action = action; if (action != null) { actionSettings = action.GetSettings(planner.GetCurrentAgent(), goal); } if (this.parent != null) { state = this.parent.GetState(); // g(node) g = parent.GetPathCost(); } else { state = planner.GetCurrentAgent().GetMemory().GetWorldState(); } var nextAction = parent == null ? null : parent.action; if (action != null) { // backward search does NOT support negative preconditions // since in backward search we relax the problem all preconditions are valid but are added to the current goal var preconditions = action.GetPreconditions(newGoal, nextAction); goal = newGoal + preconditions; var effects = action.GetEffects(newGoal, nextAction); state += effects; g += action.GetCost(newGoal, nextAction); // removing current action effects from goal, no need to do with to the whole state // since the state is the sum of all the previous actions's effects. var missingState = new ReGoapState(); goal.MissingDifference(effects, ref missingState); goal = missingState; // this is needed every step to make sure that any precondition is not already satisfied // by the world state var worldMissingState = new ReGoapState(); goal.MissingDifference(planner.GetCurrentAgent().GetMemory().GetWorldState(), ref worldMissingState); goal = worldMissingState; } else { var diff = new ReGoapState(); newGoal.MissingDifference(state, ref diff); goal = diff; } h = goal.Count; // f(node) = g(node) + h(node) cost = g + h * heuristicMultiplier; }
public static ReGoapNode <T, W> Instantiate(IGoapPlanner <T, W> planner, ReGoapState <T, W> newGoal, ReGoapNode <T, W> parent, IReGoapAction <T, W> action) { if (cachedNodes == null) { cachedNodes = new Stack <ReGoapNode <T, W> >(); } ReGoapNode <T, W> node = cachedNodes.Count > 0 ? cachedNodes.Pop() : new ReGoapNode <T, W>(); node.Init(planner, newGoal, parent, action); return(node); }
private void OnDonePlanning(Queue <ReGoapNode> _reGoapNodeList) { startedPlanning = false; if (_reGoapNodeList.Count <= 0) { return; } if (reGoapNode != null) { reGoapNode.action.Exit(); reGoapNode = null; } reGoapNodeList = _reGoapNodeList; PushAction(); }
protected virtual void Awake() { ReGoapNode <T, W> .Warmup(NodeWarmupCount); ReGoapState <T, W> .Warmup(StatesWarmupCount); ReGoapLogger.Level = LogLevel; if (Instance != null) { Destroy(this); var errorString = "[GoapPlannerManager] Trying to instantiate a new manager but there can be only one per scene."; ReGoapLogger.LogError(errorString); throw new UnityException(errorString); } Instance = this; doneWorks = new List <ReGoapPlanWork <T, W> >(); ReGoapPlannerThread <T, W> .WorksQueue = new Queue <ReGoapPlanWork <T, W> >(); planners = new ReGoapPlannerThread <T, W> [ThreadsCount]; threads = new Thread[ThreadsCount]; if (MultiThread) { ReGoapLogger.Log(String.Format("[GoapPlannerManager] Running in multi-thread mode ({0} threads).", ThreadsCount)); for (int i = 0; i < ThreadsCount; i++) { planners[i] = new ReGoapPlannerThread <T, W>(PlannerSettings, OnDonePlan); var thread = new Thread(planners[i].MainLoop); thread.Start(); threads[i] = thread; } } // no threads run else { ReGoapLogger.Log("[GoapPlannerManager] Running in single-thread mode."); planners[0] = new ReGoapPlannerThread <T, W>(PlannerSettings, OnDonePlan); } }
protected virtual void PushAction() { if (reGoapNode != null) { reGoapNode.action.Exit(); reGoapNode = null; } if (reGoapNodeList.Count <= 0) { return; } if (reGoapNodeList.Count == 0) { CalculateNewGoal(); } else { reGoapNode = reGoapNodeList.Dequeue(); reGoapNode.action.Run(reGoapNode.actionSettings, DoActionEnd, WarnActionFailure); } }
public IReGoapGoal <T, W> Plan(IReGoapAgent <T, W> agent, IReGoapGoal <T, W> blacklistGoal = null, Queue <ReGoapActionState <T, W> > currentPlan = null, Action <IReGoapGoal <T, W> > callback = null) { ReGoapLogger.Log("[ReGoalPlanner] Starting planning calculation for agent: " + agent); goapAgent = agent; Calculated = false; currentGoal = null; var possibleGoals = new List <IReGoapGoal <T, W> >(); foreach (var goal in goapAgent.GetGoalsSet()) { if (goal == blacklistGoal) { continue; } goal.Precalculations(this); if (goal.IsGoalPossible()) { possibleGoals.Add(goal); } } possibleGoals.Sort((x, y) => x.GetPriority().CompareTo(y.GetPriority())); while (possibleGoals.Count > 0) { currentGoal = possibleGoals[possibleGoals.Count - 1]; possibleGoals.RemoveAt(possibleGoals.Count - 1); var goalState = currentGoal.GetGoalState(); // can't work with dynamic actions, of course if (!settings.UsingDynamicActions) { var wantedGoalCheck = currentGoal.GetGoalState(); // we check if the goal can be archived through actions first, so we don't brute force it with A* if we can't foreach (var action in goapAgent.GetActionsSet()) { action.Precalculations(goapAgent, goalState); if (!action.CheckProceduralCondition(goapAgent, wantedGoalCheck)) { continue; } // check if the effects of all actions can archieve currentGoal var previous = wantedGoalCheck; wantedGoalCheck = ReGoapState <T, W> .Instantiate(); previous.MissingDifference(action.GetEffects(wantedGoalCheck), ref wantedGoalCheck); } // can't validate goal if (wantedGoalCheck.Count > 0) { currentGoal = null; continue; } } goalState = (ReGoapState <T, W>)goalState.Clone(); var leaf = (ReGoapNode <T, W>)astar.Run( ReGoapNode <T, W> .Instantiate(this, goalState, null, null), goalState, settings.MaxIterations, settings.PlanningEarlyExit); if (leaf == null) { currentGoal = null; continue; } var path = leaf.CalculatePath(); if (currentPlan != null && currentPlan == path) { currentGoal = null; break; } currentGoal.SetPlan(path); break; } Calculated = true; if (callback != null) { callback(currentGoal); } if (currentGoal != null) { ReGoapLogger.Log(string.Format("[ReGoapPlanner] Calculated plan for goal '{0}', plan length: {1}", currentGoal, currentGoal.GetPlan().Count)); } else { ReGoapLogger.LogWarning("[ReGoapPlanner] Error while calculating plan."); } return(currentGoal); }