private void CreateIdleState() { idleState = (fsm, gameObj) => { // GOAP planning // get the world state and the goal we want to plan for HashSet <KeyValuePair <string, object> > worldState = enemyTypeDataProvider.GetWorldState(); HashSet <KeyValuePair <string, object> > goal = enemyTypeDataProvider.CreateGoalState(); // Plan Stack <GoapAction> plan = planner.Plan(worldState, goal); if (plan != null) { // we have a plan, hooray! currentActions = plan; enemyTypeDataProvider.PlanFound(goal, plan); fsm.PopState(); // switch to PerformAction state fsm.PushState(performActionState); } else { // ugh, we couldn't get a plan Debug.Log("Failed Plan: " + goal); enemyTypeDataProvider.PlanFailed(goal); fsm.PopState(); // switch back to IdleAction state fsm.PushState(idleState); } }; }
private void CreatePerformActionState() { performActionState = (fsm, gameObj) => { // perform the action if (!HasActionPlan()) { // no actions to perform Debug.Log("<color=red>Done actions</color>"); fsm.PopState(); fsm.PushState(idleState); enemyTypeDataProvider.ActionsFinished(); return; } GoapAction action = currentActions.Peek(); if (action.IsDone()) { // the action is done. Remove it so we can perform the next one currentActions.Pop(); } 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.Perform(gameObj); if (!success) { // action failed, we need to plan again fsm.PopState(); fsm.PushState(idleState); enemyTypeDataProvider.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); enemyTypeDataProvider.ActionsFinished(); } }; }
private void CreateMoveToState() { moveToState = (fsm, gameObj) => { // move the game object GoapAction action = currentActions.Peek(); if (action.RequiresInRange() && action.target == null) { Debug.Log("Fatal error: Action requires a target but has none. Planning failed. You did not assign the target in your Action.checkProceduralPrecondition()"); fsm.PopState(); // move fsm.PopState(); // perform fsm.PushState(idleState); return; } // get the agent to move itself Debug.Log("Move to do: " + action.name); if (enemyTypeDataProvider.MoveAgent(action)) { fsm.PopState(); } }; }