protected virtual void Awake() { enabled = false; effects = ReGoapState.Instantiate(); preconditions = ReGoapState.Instantiate(); }
protected virtual void Awake() { enabled = false; effects = ReGoapState <T, W> .Instantiate(); preconditions = ReGoapState <T, W> .Instantiate(); genericValues = new Dictionary <string, object>(); }
protected virtual void Awake() { state = ReGoapState <T, W> .Instantiate(); sensors = GetComponents <IReGoapSensor <T, W> >(); foreach (var sensor in sensors) { sensor.Init(this); } }
private void Init(IGoapPlanner <T, W> planner, ReGoapState <T, W> newGoal, ReGoapNode <T, W> parent, IReGoapAction <T, W> action) { expandList.Clear(); this.planner = planner; this.parent = parent; this.action = action; if (action != null) { actionSettings = action.GetSettings(planner.GetCurrentAgent(), newGoal); } if (parent != null) { state = parent.GetState().Clone(); // g(node) g = parent.GetPathCost(); } else { state = planner.GetCurrentAgent().GetMemory().GetWorldState().Clone(); } var nextAction = parent == null ? null : parent.action; if (action != null) { // 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.AddFromState(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. goal.ReplaceWithMissingDifference(effects); // this is needed every step to make sure that any precondition is not already satisfied // by the world state goal.ReplaceWithMissingDifference(planner.GetCurrentAgent().GetMemory().GetWorldState()); } else { var diff = ReGoapState <T, W> .Instantiate(); newGoal.MissingDifference(state, ref diff); goal = diff; } h = goal.Count; // f(node) = g(node) + h(node) cost = g + h * heuristicMultiplier; }
private void Init(IGoapPlanner <T, W> planner, ReGoapState <T, W> newGoal, ReGoapNode <T, W> parent, IReGoapAction <T, W> action) { expandList.Clear(); this.planner = planner; this.parent = parent; this.action = action; if (action != null) { actionSettings = action.GetSettings(planner.GetCurrentAgent(), newGoal); } if (parent != null) { state = parent.GetState().Clone(); // g(node) g = parent.GetPathCost(); } else { state = planner.GetCurrentAgent().GetMemory().GetWorldState().Clone(); } var nextAction = parent == null ? null : parent.action; if (action != null) { // create a new instance of the goal based on the paren't goal goal = ReGoapState <T, W> .Instantiate(newGoal); var preconditions = action.GetPreconditions(goal, nextAction); var effects = action.GetEffects(goal, nextAction); // adding the action's effects to the current node's state state.AddFromState(effects); // addding the action's cost to the node's total cost g += action.GetCost(goal, nextAction); // add all preconditions of the current action to the goal goal.AddFromState(preconditions); // removes from goal all the conditions that are now fullfiled in the node's state goal.ReplaceWithMissingDifference(state); } else { var diff = ReGoapState <T, W> .Instantiate(); newGoal.MissingDifference(state, ref diff); goal = diff; } h = goal.Count; // f(node) = g(node) + h(node) cost = g + h * heuristicMultiplier; }
public virtual List <ReGoapState <T, W> > GetSettings(GoapActionStackData <T, W> stackData) { if (stackData.settings != null) { return(new List <ReGoapState <T, W> > { stackData.settings }); } else { return(new List <ReGoapState <T, W> > { ReGoapState <T, W> .Instantiate() }); } }
public static ReGoapTestGoal GetCustomGoal(GameObject gameObject, string name, Dictionary <string, object> goalState, int priority = 1) { var customGoal = gameObject.AddComponent <ReGoapTestGoal>(); customGoal.Name = name; customGoal.SetPriority(priority); customGoal.Init(); var goal = ReGoapState <string, object> .Instantiate(); foreach (var pair in goalState) { goal.Set(pair.Key, pair.Value); } customGoal.SetGoalState(goal); return(customGoal); }
public void TestReGoapStateMissingDifference() { var state = ReGoapState <string, object> .Instantiate(); state.Set("var0", true); state.Set("var1", "string"); state.Set("var2", 1); var otherState = ReGoapState <string, object> .Instantiate(); otherState.Set("var1", "stringDifferent"); otherState.Set("var2", 1); var differences = ReGoapState <string, object> .Instantiate(); var count = state.MissingDifference(otherState, ref differences); Assert.That(count, Is.EqualTo(2)); Assert.That(differences.Get("var0"), Is.EqualTo(true)); Assert.That(differences.Get("var1"), Is.EqualTo("string")); Assert.That(differences.HasKey("var2"), Is.EqualTo(false)); }
protected virtual void Awake() { lastCalculationTime = -100; goals = new List <ReGoapGoal>(GetComponents <ReGoapGoal>()); possibleGoalsDirty = true; actions = new List <ReGoapAction>(GetComponents <ReGoapAction>()); for (int i = 0; i < actions.Count; ++i) { actions[i].SetAgent(this); } state = ReGoapState.Instantiate(); sensors = GetComponents <ReGoapSensor>(); foreach (var sensor in sensors) { sensor.Init(this); } }
public void TestReGoapStateAddOperator() { var state = ReGoapState <string, object> .Instantiate(); state.Set("var0", true); state.SetStructValue("var1", StructValue.CreateIntArithmetic(10)); state.SetStructValue("var2", StructValue.CreateFloatArithmetic(100f)); var otherState = ReGoapState <string, object> .Instantiate(); otherState.SetStructValue("var1", StructValue.CreateIntArithmetic(20)); // 2nd one replaces the first otherState.SetStructValue("var2", StructValue.CreateFloatArithmetic(-20f)); otherState.Set("var3", 10.1f); Assert.That(state.Count, Is.EqualTo(3)); state.AddFromState(otherState); Assert.That(otherState.Count, Is.EqualTo(3)); Assert.That(state.Count, Is.EqualTo(4)); Assert.That(state.Get("var0"), Is.EqualTo(true)); Assert.That(state.Get("var1"), Is.EqualTo(30)); Assert.That(state.Get("var2"), Is.EqualTo(80f)); Assert.That(state.Get("var3"), Is.EqualTo(10.1f)); }
public void TestReGoapStateAddOperator() { var state = ReGoapState <string, object> .Instantiate(); state.Set("var0", true); state.Set("var1", "string"); state.Set("var2", 1); var otherState = ReGoapState <string, object> .Instantiate(); otherState.Set("var2", "new2"); // 2nd one replaces the first otherState.Set("var3", true); otherState.Set("var4", 10.1f); Assert.That(state.Count, Is.EqualTo(3)); state.AddFromState(otherState); Assert.That(otherState.Count, Is.EqualTo(3)); Assert.That(state.Count, Is.EqualTo(5)); // var2 on first is replaced by var2 on second Assert.That(state.Get("var0"), Is.EqualTo(true)); Assert.That(state.Get("var1"), Is.EqualTo("string")); Assert.That(state.Get("var2"), Is.EqualTo("new2")); Assert.That(state.Get("var3"), Is.EqualTo(true)); Assert.That(state.Get("var4"), Is.EqualTo(10.1f)); }
public static ReGoapTestAction GetCustomAction(GameObject gameObject, string name, Dictionary <string, object> preconditionsBools, Dictionary <string, object> effectsBools, int cost = 1) { var effects = ReGoapState <string, object> .Instantiate(); var preconditions = ReGoapState <string, object> .Instantiate(); var customAction = gameObject.AddComponent <ReGoapTestAction>(); customAction.Name = name; customAction.Init(); foreach (var pair in effectsBools) { _AddIntoReGoapState(effects, pair.Key, pair.Value); } customAction.SetEffects(effects); foreach (var pair in preconditionsBools) { _AddIntoReGoapState(preconditions, pair.Key, pair.Value); } customAction.SetPreconditions(preconditions); customAction.Cost = cost; return(customAction); }
private void UpdateGoapNodes <T, W>(IReGoapAgent <T, W> agent) { if (nodes == null) { nodes = new List <ReGoapNodeEditor>(); } if (agentHelper == null || agent == null || !agent.IsActive() || agent.GetMemory() == null) { return; } nodes.Clear(); var width = 300f; var height = 70f; var nodePosition = new Vector2(0f, 60f); var nodeMiddleY = new Vector2(0f, height * 0.5f); ReGoapNodeEditor?previousNode = null; foreach (var goal in agent.GetGoalsSet()) { if (goal.GetGoalState() == null) { continue; } var text = string.Format("<b>GOAL</b> <i>{0}</i>\n", goal); foreach (var keyValue in goal.GetGoalState().GetValues()) { text += string.Format("<b>'{0}'</b> = <i>'{1}'</i>", keyValue.Key, keyValue.Value); } var style = nodeStyle; if (agent.IsActive() && agent.GetCurrentGoal() == goal) { style = activeStyle; } var newNode = DrawGenericNode(text, width, height, style, ref nodePosition); if (previousNode.HasValue) { var startPosition = previousNode.Value.Rect.max - nodeMiddleY - new Vector2(10f, 0f); var endPosition = newNode.Rect.min + nodeMiddleY + new Vector2(10f, 0f); Handles.DrawLine(startPosition, endPosition); } previousNode = newNode; } previousNode = null; nodePosition = new Vector2(0f, nodePosition.y + height + 10); height = 66; var maxHeight = height; var emptyGoal = agent.InstantiateNewState(); GoapActionStackData <T, W> stackData; stackData.agent = agent; stackData.currentState = agent.GetMemory().GetWorldState(); stackData.goalState = emptyGoal; stackData.next = null; stackData.settings = ReGoapState <T, W> .Instantiate(); foreach (var action in agent.GetActionsSet()) { var curHeight = height; var text = string.Format("<b>POSS.ACTION</b> <i>{0}</i>\n", action.GetName()); text += "-<b>preconditions</b>-\n"; var preconditionsDifferences = agent.InstantiateNewState(); var preconditions = action.GetPreconditions(stackData); if (preconditions == null) { continue; } preconditions.MissingDifference(stackData.currentState, ref preconditionsDifferences); foreach (var preconditionPair in preconditions.GetValues()) { curHeight += 13; var color = "#004d00"; if (preconditionsDifferences.GetValues().ContainsKey(preconditionPair.Key)) { color = "#800000"; } text += string.Format("<color={2}>'<b>{0}</b>' = '<i>{1}</i>'</color>\n", preconditionPair.Key, preconditionPair.Value, color); } preconditionsDifferences.Recycle(); text += "-<b>effects</b>-\n"; foreach (var effectPair in action.GetEffects(stackData).GetValues()) { curHeight += 13; text += string.Format("'<b>{0}</b>' = '<i>{1}</i>'\n", effectPair.Key, effectPair.Value); } curHeight += 13; var proceduralCheck = action.CheckProceduralCondition(stackData); text += string.Format("<color={0}>-<b>proceduralCondition</b>: {1}</color>\n", proceduralCheck ? "#004d00" : "#800000", proceduralCheck); maxHeight = Mathf.Max(maxHeight, curHeight); nodeMiddleY = new Vector2(0f, curHeight * 0.5f); var newNode = DrawGenericNode(text, width, curHeight, possibleActionStyle, ref nodePosition); if (previousNode.HasValue) { var startPosition = previousNode.Value.Rect.max - nodeMiddleY - new Vector2(10f, 0f); var endPosition = newNode.Rect.min + nodeMiddleY + new Vector2(10f, 0f); Handles.DrawLine(startPosition, endPosition); } previousNode = newNode; } previousNode = null; nodePosition.x = 0; nodePosition.y += maxHeight + 10; height = 40; nodeMiddleY = new Vector2(0f, height * 0.5f); if (agent.GetCurrentGoal() != null) { foreach (var action in agent.GetStartingPlan().ToArray()) { var style = actionNodeStyle; if (action.Action.IsActive()) { style = activeActionNodeStyle; } var text = string.Format("<b>ACTION</b> <i>{0}</i>\n", action.Action.GetName()); var newNode = DrawGenericNode(text, width, height, style, ref nodePosition); if (previousNode.HasValue) { var startPosition = previousNode.Value.Rect.max - nodeMiddleY - new Vector2(10f, 0f); var endPosition = newNode.Rect.min + nodeMiddleY + new Vector2(10f, 0f); Handles.DrawLine(startPosition, endPosition); } previousNode = newNode; } } if (agent.GetMemory() != null) { nodePosition = new Vector2(0, nodePosition.y + height + 10); width = 500; height = 40; nodeMiddleY = new Vector2(0f, height * 0.5f); var nodeText = "<b>WORLD STATE</b>\n"; foreach (var pair in agent.GetMemory().GetWorldState().GetValues()) { nodeText += string.Format("'<b>{0}</b>' = '<i>{1}</i>'\n", pair.Key, pair.Value); height += 13; } DrawGenericNode(nodeText, width, height, worldStateStyle, ref nodePosition); } }
private void Init(IGoapPlanner <T, W> planner, ReGoapState <T, W> newGoal, ReGoapNode <T, W> parent, IReGoapAction <T, W> action) { expandList.Clear(); tmpKeys.Clear(); this.planner = planner; this.parent = parent; this.action = action; if (action != null) { actionSettings = action.GetSettings(planner.GetCurrentAgent(), newGoal); } if (parent != null) { state = parent.GetState().Clone(); // g(node) g = parent.GetPathCost(); } else { state = planner.GetCurrentAgent().GetMemory().GetWorldState().Clone(); } var nextAction = parent == null ? null : parent.action; if (action != null) { // create a new instance of the goal based on the paren't goal goal = ReGoapState <T, W> .Instantiate(); var tmpGoal = ReGoapState <T, W> .Instantiate(newGoal); var preconditions = action.GetPreconditions(tmpGoal, nextAction); var effects = action.GetEffects(tmpGoal, nextAction); // adding the action's effects to the current node's state state.AddFromState(effects); // addding the action's cost to the node's total cost g += action.GetCost(tmpGoal, nextAction); //// add all preconditions of the current action to the goal //tmpGoal.AddFromState(preconditions); //// removes from goal all the conditions that are now fulfilled in the node's state //tmpGoal.ReplaceWithMissingDifference(state); ////goal.ReplaceWithMissingDifference(effects); // collect all keys from goal & precondition, unique-ed foreach (var pr in tmpGoal.GetValues()) { var k = pr.Key; if (!tmpKeys.Contains(k)) { tmpKeys.Add(k); } } foreach (var pr in preconditions.GetValues()) { var k = pr.Key; if (!tmpKeys.Contains(k)) { tmpKeys.Add(k); } } // process each keys foreach (var k in tmpKeys) { StructValue goalValue, effectValue, precondValue, stateValue, protoValue; tmpGoal.GetValues().TryGetValue(k, out goalValue); effects.GetValues().TryGetValue(k, out effectValue); preconditions.GetValues().TryGetValue(k, out precondValue); state.GetValues().TryGetValue(k, out stateValue); StructValue.EValueType valueType; _GetValueType(ref goalValue, ref effectValue, ref precondValue, ref stateValue, out valueType, out protoValue); if (valueType == StructValue.EValueType.Arithmetic) { //_EnsureArithStructValueInited(ref goalValue, ref protoValue); _EnsureArithStructValueInited(ref effectValue, ref protoValue); _EnsureArithStructValueInited(ref precondValue, ref protoValue); _EnsureArithStructValueInited(ref stateValue, ref protoValue); if (!goalValue.Inited) { goalValue = StructValue.CopyCreate(ref stateValue, -(Convert.ToSingle(stateValue.v) - Convert.ToSingle(effectValue.v))); } float fGoal = Convert.ToSingle(goalValue.v); float fEffect = Convert.ToSingle(effectValue.v); float fPrecond = Convert.ToSingle(precondValue.v); float fState = Convert.ToSingle(stateValue.v); float finalV = Math.Max( fGoal - fEffect, Math.Min(fPrecond, fPrecond - fState) ); var sv = StructValue.CopyCreate(ref protoValue, finalV); goal.SetStructValue(k, sv); } else if (valueType == StructValue.EValueType.Other) { //ReplaceWithMissingDifference if (stateValue.Inited && goalValue.Inited && goalValue.IsFulfilledBy(stateValue)) { goalValue.Invalidate(); } // AddFromPrecond // 1. if the precond is satisfied by the memory start state, then discard // 2. else this newly added goal from precond, should not be removed due to fulfilled by curStateValue if (precondValue.Inited) { bool preCondfulfilledByMem = false; var startMemoryState = planner.GetCurrentAgent().GetMemory().GetWorldState(); StructValue startMemoryValue; if (startMemoryState.GetValues().TryGetValue(k, out startMemoryValue)) { if (startMemoryValue.Inited && precondValue.IsFulfilledBy(startMemoryValue)) { preCondfulfilledByMem = true; } } if (!preCondfulfilledByMem) { if (goalValue.Inited) { goalValue = goalValue.MergeWith(precondValue); } else { goalValue = precondValue; } } } if (goalValue.Inited) { goal.SetStructValue(k, goalValue); } } else { UnityEngine.Debug.LogError("Unexpected StructValue type: " + valueType); } }// foreach (var k in tmpKeys) tmpGoal.Recycle(); } else { var diff = ReGoapState <T, W> .Instantiate(); newGoal.MissingDifference(state, ref diff); goal = diff; } h = _CalculateH(); // f(node) = g(node) + h(node) cost = g + h * planner.GetSettings().HeuristicMultiplier; }
public void TestDynamicAction() { var gameObject = new GameObject(); // settings these value to make sure that the planning chooses weaponA, since the pathing // weaponA -> ammoA -> enemy is actually cheaper, even if weaponC is very close to the enemy // without dynamic cost weaponC would always be chosen // we also add weaponB and ammoB to show the reconcileStartPosition logic // with this requirement in the goal and this action, we push as cost a goto to the player position // this effectively makes the plan: weaponB -> ammoB -> enemy more expensive, without reconciling with the starting position this plan would have been the best. var playerPosition = Vector2.zero; var enemyPosition = new Vector2(0, 100); var weaponAPosition = new Vector2(0, 50); var ammoAPosition = new Vector2(0, 60); var weaponBPosition = new Vector2(0, 115); var ammoBPosition = new Vector2(0, 115); var weaponCPosition = new Vector2(-5, 100); var weaponRange = 20.0f; ReGoapTestsHelper.GetCustomAction(gameObject, "ShootEnemy", new Dictionary <string, object> { { "weaponReady", true }, { "isAt", enemyPosition }, { "inRange", weaponRange } }, new Dictionary <string, object> { { "shootEnemy", true } }, 100); ReGoapTestsHelper.GetCustomAction(gameObject, "ReloadWeapon", new Dictionary <string, object> { { "hasWeapon", true }, { "hasAmmo", true } }, new Dictionary <string, object> { { "weaponReady", true } }, 20); #region getWeapon var getWeapon = ReGoapTestsHelper.GetCustomAction(gameObject, "GetWeapon", new Dictionary <string, object> { }, new Dictionary <string, object> { { "hasWeapon", true } }, 5); getWeapon.CustomPreconditionsGetter = (ref ReGoapState <string, object> preconditions, GoapActionStackData <string, object> stackData) => { preconditions.Clear(); if (stackData.settings.HasKey("weaponPosition")) { preconditions.Set("isAt", (Vector2)stackData.settings.Get("weaponPosition")); } }; getWeapon.CustomEffectsGetter = (ref ReGoapState <string, object> effects, GoapActionStackData <string, object> stackData) => { effects.Clear(); if (stackData.settings.HasKey("weaponPosition")) { effects.Set("hasWeapon", true); } }; getWeapon.CustomSettingsGetter = (GoapActionStackData <string, object> stackData) => { var results = new List <ReGoapState <string, object> >(); if (stackData.currentState.HasKey("weaponPositions") && stackData.currentState.HasKey("isAt")) { var currentPosition = (Vector2)stackData.currentState.Get("isAt"); foreach (var objectPosition in (List <Vector2>)stackData.currentState.Get("weaponPositions")) { ReGoapState <string, object> settings = ReGoapState <string, object> .Instantiate(); settings.Set("weaponPosition", objectPosition); results.Add(settings); } } return(results); }; #endregion #region getAmmo var getAmmo = ReGoapTestsHelper.GetCustomAction(gameObject, "GetAmmo", new Dictionary <string, object> { }, new Dictionary <string, object> { { "hasAmmo", true } }, 3); getAmmo.CustomPreconditionsGetter = (ref ReGoapState <string, object> preconditions, GoapActionStackData <string, object> stackData) => { preconditions.Clear(); if (stackData.settings.HasKey("ammoPosition")) { preconditions.Set("isAt", (Vector2)stackData.settings.Get("ammoPosition")); } }; getAmmo.CustomEffectsGetter = (ref ReGoapState <string, object> effects, GoapActionStackData <string, object> stackData) => { effects.Clear(); if (stackData.settings.HasKey("ammoPosition")) { effects.Set("hasAmmo", true); } }; getAmmo.CustomSettingsGetter = (GoapActionStackData <string, object> stackData) => { var results = new List <ReGoapState <string, object> >(); if (stackData.currentState.HasKey("ammoPositions") && stackData.currentState.HasKey("isAt")) { var currentPosition = (Vector2)stackData.currentState.Get("isAt"); foreach (var objectPosition in (List <Vector2>)stackData.currentState.Get("ammoPositions")) { ReGoapState <string, object> settings = ReGoapState <string, object> .Instantiate(); settings.Set("ammoPosition", objectPosition); results.Add(settings); } } return(results); }; #endregion #region dynamicGoTo var dynamicGoTo = ReGoapTestsHelper.GetCustomAction(gameObject, "GoTo", new Dictionary <string, object> { }, new Dictionary <string, object> { }); dynamicGoTo.CustomCostGetter = (ref float cost, GoapActionStackData <string, object> stackData) => { // base value to avoid free action cost = 1.0f; var inRange = 0.0f; if (stackData.settings.HasKey("inRange")) { inRange = (float)stackData.settings.Get("inRange"); } if (stackData.settings.HasKey("isAt") && stackData.currentState.HasKey("isAt")) { var wantedPosition = (Vector2)stackData.settings.Get("isAt"); var currentPosition = (Vector2)stackData.currentState.Get("isAt"); cost = (wantedPosition - currentPosition).magnitude - inRange; if (cost < 0) { cost = 0; } } }; dynamicGoTo.CustomEffectsGetter = (ref ReGoapState <string, object> effects, GoapActionStackData <string, object> stackData) => { effects.Clear(); if (stackData.settings.HasKey("isAt")) { var wantedPosition = (Vector2)stackData.settings.Get("isAt"); effects.Set("isAt", wantedPosition); } if (stackData.settings.HasKey("inRange")) { var inRange = (float)stackData.settings.Get("inRange"); effects.Set("inRange", inRange); } }; dynamicGoTo.CustomSettingsGetter = (GoapActionStackData <string, object> stackData) => { var newSettings = ReGoapState <string, object> .Instantiate(); Vector2 wantedPosition = Vector2.zero; float inRange = 0.0f; if (stackData.goalState.HasKey("isAt")) { wantedPosition = (Vector2)stackData.goalState.Get("isAt"); } if (stackData.goalState.HasKey("inRange")) { inRange = (float)stackData.goalState.Get("inRange"); } newSettings.Set("isAt", wantedPosition); newSettings.Set("inRange", inRange); return(new List <ReGoapState <string, object> > { newSettings }); }; #endregion #region reconcileStartPosition var reconcileStartPosition = ReGoapTestsHelper.GetCustomAction(gameObject, "ReconcileStartPosition", new Dictionary <string, object> { }, new Dictionary <string, object> { }, 1); reconcileStartPosition.CustomPreconditionsGetter = (ref ReGoapState <string, object> preconditions, GoapActionStackData <string, object> stackData) => { preconditions.Clear(); // this could be fetched from the world memory, in a custom action class preconditions.Set("isAt", playerPosition); }; reconcileStartPosition.CustomEffectsGetter = (ref ReGoapState <string, object> effects, GoapActionStackData <string, object> stackData) => { effects.Clear(); // we want this action to work only if no other goal has to be archived if (stackData.goalState.HasKey("reconcileStartPosition") && stackData.goalState.Count == 1) { effects.Set("reconcileStartPosition", true); } }; #endregion var theGoal = ReGoapTestsHelper.GetCustomGoal(gameObject, "ShootEnemy", new Dictionary <string, object> { { "shootEnemy", true }, { "reconcileStartPosition", true } }); var memory = gameObject.AddComponent <ReGoapTestMemory>(); memory.Init(); memory.SetValue("enemyPosition", enemyPosition); memory.SetValue("ammoPositions", new List <Vector2> { ammoAPosition, ammoBPosition }); memory.SetValue("weaponPositions", new List <Vector2> { weaponAPosition, weaponBPosition, weaponCPosition }); var agent = gameObject.AddComponent <ReGoapTestAgent>(); agent.Init(); var plan = GetPlanner(dynamicActions: true).Plan(agent, null, null, null); }
protected virtual void Awake() { goal = ReGoapState <T, W> .Instantiate(); }
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) { if (ReGoapLogger.Level == ReGoapLogger.DebugLevel.Full) { 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; } } //Utilities.ReGoapLogger.Log(string.Format("**** Goal: {0}, Expected State = ({1})", currentGoal.GetName(), goalState)); goalState = goalState.Clone(); var leaf = (ReGoapNode <T, W>)astar.Run( ReGoapNode <T, W> .Instantiate(this, goalState, null, null), goalState, settings.MaxIterations, settings.PlanningEarlyExit, debugPlan: agent.debugPlan); if (leaf == null) { currentGoal = null; continue; } var result = leaf.CalculatePath(); if (currentPlan != null && currentPlan == result) { currentGoal = null; break; } if (result.Count == 0) { currentGoal = null; continue; } currentGoal.SetPlan(result); 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)); if (ReGoapLogger.Level == ReGoapLogger.DebugLevel.Full) { int i = 0; foreach (var action in currentGoal.GetPlan()) { ReGoapLogger.Log(string.Format("[ReGoapPlanner] {0}) {1}", i++, action.Action)); } } } else { ReGoapLogger.LogWarning("[ReGoapPlanner] Error while calculating plan."); } return(currentGoal); }
public virtual ReGoapState <T, W> InstantiateNewState() { return(ReGoapState <T, W> .Instantiate()); }
protected virtual void Awake() { reGoapState = ReGoapState.Instantiate(); }
private void Init(IGoapPlanner <T, W> planner, ReGoapState <T, W> newGoal, ReGoapNode <T, W> parent, IReGoapAction <T, W> action, ReGoapState <T, W> settings) { expandList.Clear(); this.planner = planner; this.parent = parent; this.action = action; if (settings != null) { this.actionSettings = settings.Clone(); } if (parent != null) { state = parent.GetState().Clone(); // g(node) g = parent.GetPathCost(); } else { state = planner.GetCurrentAgent().GetMemory().GetWorldState().Clone(); } var nextAction = parent == null ? null : parent.action; if (action != null) { // create a new instance of the goal based on the paren't goal goal = ReGoapState <T, W> .Instantiate(newGoal); GoapActionStackData <T, W> stackData; stackData.currentState = state; stackData.goalState = goal; stackData.next = action; stackData.agent = planner.GetCurrentAgent(); stackData.settings = actionSettings; var preconditions = action.GetPreconditions(stackData); var effects = action.GetEffects(stackData); // addding the action's cost to the node's total cost g += action.GetCost(stackData); // adding the action's effects to the current node's state state.AddFromState(effects); // removes from goal all the conditions that are now fullfiled in the action's effects goal.ReplaceWithMissingDifference(effects); // add all preconditions of the current action to the goal goal.AddFromState(preconditions); } else { goal = newGoal; } h = goal.Count; // f(node) = g(node) + h(node) cost = g + h * heuristicMultiplier; // additionally calculate the goal without any world effect to understand if we are done var diff = ReGoapState <T, W> .Instantiate(); goal.MissingDifference(planner.GetCurrentAgent().GetMemory().GetWorldState(), ref diff); goalMergedWithWorld = diff; }
private void Init(ReGoapAgent agent, ReGoapState newGoalState, ReGoapNode parent, ReGoapAction action) { expandList.Clear(); ReGoapState goal = null; this.reGoapAgent = agent; this.parentNode = parent; this.action = action; if (action != null) { actionSettings = action.GetSettings(newGoalState); } if (parentNode != null) { agentReGoapState = parentNode.GetState().Clone(); g = parentNode.GetPathCost(); } else { ReGoapState reGoapState = agent.GetWorldState(); agentReGoapState = reGoapState.Clone(); } if (action != null) { // create a new instance of the goal based on the paren't goal goal = ReGoapState.Instantiate(newGoalState); var preconditions = action.GetPreconditions(goal); var effects = action.GetEffects(goal); // adding the action's effects to the current node's state agentReGoapState.AddFromState(effects); // addding the action's cost to the node's total cost g += action.GetCost(); // add all preconditions of the current action to the goal goal.AddFromState(preconditions); // removes from goal all the conditions that are now fullfiled in the node's state goal.ReplaceWithMissingDifference(agentReGoapState); } else { goal = newGoalState.MissingDifference(agentReGoapState); } h = goal.Count; cost = g + h; //Expand(goal); expandList.Clear(); List <ReGoapAction> actionsList = reGoapAgent.GetActionsSet(); for (var index = actionsList.Count - 1; index >= 0; index--) { ReGoapAction possibleAction = actionsList[index]; if (!possibleAction.CheckProceduralCondition()) // 执行条件不满足排除掉 { continue; } ReGoapState precond = possibleAction.GetPreconditions(goal); ReGoapState effects = possibleAction.GetEffects(goal); if (!ReGoapState.HasAny(effects, goal)) // any effect is the current goal { continue; } if (!ReGoapState.HasAnyConflict(precond, goal)) { ReGoapNode reGoapNode = new ReGoapNode(reGoapAgent, goal, this, possibleAction); expandList.Add(reGoapNode); } } }
public virtual ReGoapState <T, W> GetPreconditions(GoapActionStackData <T, W> stackData) { return(ReGoapState <T, W> .Instantiate()); }
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) { 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())); var currentState = agent.GetMemory().GetWorldState(); 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(); GoapActionStackData <T, W> stackData; stackData.agent = goapAgent; stackData.currentState = currentState; stackData.goalState = goalState; stackData.next = null; stackData.settings = null; // 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(stackData); if (!action.CheckProceduralCondition(stackData)) { continue; } // check if the effects of all actions can archieve currentGoal var previous = wantedGoalCheck; wantedGoalCheck = ReGoapState <T, W> .Instantiate(); previous.MissingDifference(action.GetEffects(stackData), ref wantedGoalCheck); } // finally push the current world state var current = wantedGoalCheck; wantedGoalCheck = ReGoapState <T, W> .Instantiate(); current.MissingDifference(GetCurrentAgent().GetMemory().GetWorldState(), ref wantedGoalCheck); // can't validate goal if (wantedGoalCheck.Count > 0) { currentGoal = null; continue; } } goalState = goalState.Clone(); var leaf = (ReGoapNode <T, W>)astar.Run( ReGoapNode <T, W> .Instantiate(this, goalState, null, null, null), goalState, settings.MaxIterations, settings.PlanningEarlyExit); if (leaf == null) { currentGoal = null; continue; } var result = leaf.CalculatePath(); if (currentPlan != null && currentPlan == result) { currentGoal = null; break; } if (result.Count == 0) { currentGoal = null; continue; } currentGoal.SetPlan(result); break; } Calculated = true; if (callback != null) { callback(currentGoal); } return(currentGoal); }