我正在尝试在unity中实现行为树,目前我为每个节点/复合体/动作使用了一个Tick()函数
我想做的是在一个序列中,例如:
-
开始遍历节点列表的for循环
-
在当前节点上启动tick函数
-
等待节点tick返回失败/成功
-
转到下一个节点并继续执行步骤1
我遇到的问题是步骤3。我试图使用协程来实现这一点。
问题是断言为真,nodeStat变量为None。当执行WaitForSeconds时,控制权返回到Debug.Assert(nodeStat != Status.None);
行
public class Sequence : Composite{ protected override void Start() { status = Status.Running; } Status nodeStat = Status.None; IEnumerator Recursive(Node nod) { while (true) { Debug.Log(nod + "is running"); Status status = nod.Tick(); Debug.Log(Time.time + " " + status); if (status == Status.Running) { Debug.Log("start coroutine at : " + Time.time); yield return new WaitForSeconds(0.2f); Debug.Log("Comtinue coroutine at : " + Time.time); } else { Debug.Log("has finished coroutine"); nodeStat = status; break; } } } protected override Status Execute() { foreach(Node nod in ListaNoduri) { GameManager.Instance.StartCoroutine(Recursive(nod)); Debug.Assert(nodeStat != Status.None); if (nodeStat == Status.Failure) return Status.Failure; } return Status.Success; } protected override void Exit() { base.Exit(); } public override Status Tick() { //Debug.Log(status); return base.Tick(); }}
回答:
考虑将Execute()
变成一个协程:
IEnumerator Execute(){ foreach(Node nod in ListaNoduri) { //在继续之前等待当前节点完成 yield return GameManager.Instance.StartCoroutine(Recursive(nod)); Debug.Assert(nodeStat != Status.None); if (nodeStat == Status.Failure){ //在失败时做一些事情 yield break; } } //在成功时做一些事情}