Search code examples
c#unity-game-engineartificial-intelligence

Pause execution of a function using a coroutine untiy


I am trying to implement behaviour trees in untiy and right now i am using a Tick() function for each Node/Composite/Action

What I want to do is in a sequence,for example,is :

  1. Begin the for loop itereating in the list of nodes

  2. Start the tick function on the current node

  3. Wait until the node tick returned Failed/Success

  4. Go to the next node and continue to go to step 1

    the issue i am having is with the step 3. I am tring to accomplish this with a coroutine.

the problem is that the assertion is true, the nodeStat var is None. When the WaitFor Seconds is executed, the control gets back to Debug.Assert(nodeStat != Status.None); line

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();
    }
}

Solution

  • Consider making Execute() a coroutine:

    IEnumerator Execute()
    {
        foreach(Node nod in ListaNoduri)
        {
            //wait for the current node to be done before continuing
            yield return GameManager.Instance.StartCoroutine(Recursive(nod));
            Debug.Assert(nodeStat != Status.None);
            if (nodeStat == Status.Failure){
                //do something on failure 
                yield break;
            }
        }
        //do something on success
    }