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); dataProvider.actionsFinished(); return; } var 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(); var inRange = action.requiresInRange() ? action.isInRange() : true; if (inRange) { // we are in range, so perform the action var success = action.perform(gameObj, dataProvider.GetBlackBoard()); if (!success) { // action failed, we need to plan again fsm.popState(); fsm.pushState(idleState); 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.actionsFinished(); } }; }
/** * Plan what sequence of actions can fulfill the goal. * Returns null if a plan could not be found, or a list of the actions * that must be performed, in order, to fulfill the goal. * 计划可以实现目标的行动顺序。 * 如果找不到计划,或者操作列表,则返回null * 必须按顺序执行才能实现目标。 */ ///<summary> ///计划 ///</summary> public Queue <GoapAction> Plan(GameObject agent, HashSet <GoapAction> availableActions, Dictionary <string, bool> worldState, KeyValuePair <string, bool> goal, IGoap goap) { // reset the actions so we can start fresh with them //重置动作,以便我们可以重新开始 foreach (var a in availableActions) { a.doReset(); } // check what actions can run using their checkProceduralPrecondition //使用检查程序前置条件检查可以运行的操作 var usableActions = NodeManager.GetFreeActionSet(); foreach (var a in availableActions) { if (a.CheckProceduralPrecondition(agent, goap.GetBlackBoard())) { usableActions.Add(a); } } // we now have all actions that can run, stored in usableActions //我们现在拥有可以运行的所有操作,存储在usefulActions中 // build up the tree and record the leaf nodes that provide a solution to the goal. //构建树并记录提供目标解决方案的节点。 var leaves = new List <GoapNode>(); // build graph //构建图表 var start = NodeManager.GetFreeNode(null, 0, 0, worldState, null); //构建图 var success = BuildGraph(start, leaves, usableActions, goal); if (!success) { // oh no, we didn't get a plan //不,我们没有得到一个计划 // Debug.Log("NO PLAN"); return(null); } // get the cheapest leaf //得到最便宜的节点 GoapNode cheapest = null; foreach (var leaf in leaves) { if (cheapest == null) { cheapest = leaf; } else { if (leaf.BetterThen(cheapest)) { cheapest = leaf; } } } // get its node and work back through the parents //获取其节点并通过父节点返回 var result = new List <GoapAction>(); var n = cheapest; while (n != null) { if (n.action != null) { //在前面插入动作 result.Insert(0, n.action); // insert the action in the front } n = n.parent; } NodeManager.Release(); // we now have this action list in correct order //我们现在按正确的顺序拥有此操作列表 var queue = new Queue <GoapAction>(); foreach (var a in result) { queue.Enqueue(a); } // hooray we have a plan! //万岁,我们有一个计划! return(queue); }
/** * Plan what sequence of actions can fulfill the goal. * Returns null if a plan could not be found, or a list of the actions * that must be performed, in order, to fulfill the goal. */ public Queue <GoapAction> plan(GameObject agent, HashSet <GoapAction> availableActions, Dictionary <string, bool> worldState, KeyValuePair <string, bool> goal, IGoap goap) { // reset the actions so we can start fresh with them foreach (var a in availableActions) { a.doReset(); } // check what actions can run using their checkProceduralPrecondition var usableActions = NodeManager.GetFreeActionSet(); foreach (var a in availableActions) { if (a.checkProceduralPrecondition(agent, goap.GetBlackBoard())) { usableActions.Add(a); } } // we now have all actions that can run, stored in usableActions // build up the tree and record the leaf nodes that provide a solution to the goal. var leaves = new List <GoapNode>(); // build graph var start = NodeManager.GetFreeNode(null, 0, 0, worldState, null); var success = buildGraph(start, leaves, usableActions, goal); if (!success) { // oh no, we didn't get a plan // Debug.Log("NO PLAN"); return(null); } // get the cheapest leaf GoapNode cheapest = null; foreach (var leaf in leaves) { if (cheapest == null) { cheapest = leaf; } else { if (leaf.BetterThen(cheapest)) { cheapest = leaf; } } } // get its node and work back through the parents var result = new List <GoapAction>(); var n = cheapest; while (n != null) { if (n.action != null) { result.Insert(0, n.action); // insert the action in the front } n = n.parent; } NodeManager.Release(); // we now have this action list in correct order var queue = new Queue <GoapAction>(); foreach (var a in result) { queue.Enqueue(a); } // hooray we have a plan! return(queue); }
/// <summary> /// 创建执行操作状态 /// </summary> 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); dataProvider.ActionsFinished(); return; } var 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(); var inRange = action.RequiresInRange() ? action.IsInRange() : true; if (inRange) { // we are in range, so perform the action //我们在范围内,所以执行操作 var success = action.Perform(gameObj, dataProvider.GetBlackBoard()); if (!success) { // action failed, we need to plan again //操作失败,我们需要再次计划 fsm.popState(); fsm.pushState(idleState); 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.ActionsFinished(); } }; }