[Bug] Graphs are not fully reset when Stoping and Starting again

NodeCanvas Forums Support [Bug] Graphs are not fully reset when Stoping and Starting again

Tagged: 

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #15107
    hosnkobf
    Participant

    Description

    My game creates small jobs for the characters in the game and enqueues them. These jobs are triggering behaviour trees which need to have one ActionTask at the end which internally calls (base.ownerSystem as BehaviourTree).Stop(); My system listens to the callback to immediately trigger the next job. To avoid performance problems I also implemented pooling for the graphs. That means that the same instance of a graph can be executed multiple times.

    I now realized that the graphs behave unexpected when executed the second time.

    here is the code of my ActionTask:

    I try to explain steps to reprouce:

    1. Create a simple BehaviourTree asset with a Step-Sequencer and two actions: first for logging, second is the FinishActivity posted above.
    2. Instantiate the tree asset via code.
    3. Start the tree asset with any component in the scene as agent a new BlackBoardSource() as parentBlackboard and assign a method as callback.
    4. In the callback method, start a coroutine and wait a frame (because the graph is still marked as running when the callback is called), then start the same instance of the graph again the same way as before.

    Result:
    The graph behaves different in comparison to the first run.

    • if // base.EndAction(success: true); is commented:
      During the second run the Graph-Canvas shows both actions active although only the first should be active.
    • if base.EndAction(success: true); is not commented:
      During the second run the Graph-Canvas highlights the Finish-Action green and marks it with a checkmark. The first action is not triggered anymore.

    Expected Result:
    The graph has the same behavior every time it is stopped and started again.

    Attachments:
    You must be logged in to view attached files.
    #15112
    Gavalakis
    Keymaster

    Hello there,

    Thank you for the details of reproduction. Stoping the graph from within its own execution is indeed a bit problematic. To make this work, please change your action code to call EndAction(null) instead.

    EndAction(null) is used when we want to interrupt the action irrelevant of success or failure (which is relevant to this case since we stop the graph right after anyways), and will make the action completely reset to Resting.

    You will still need to yield 1 frame just like you said before re-starting the graph in the onFinish callback (although I am looking into this and how to avoid this requirement).

    Please let me know if the above change works for you.

    Thank you!

    Join us on Discord: https://discord.gg/97q2Rjh

    #15121
    hosnkobf
    Participant

    Hi Gavalakis,

    thank you for your reply and the potential fix.
    This fix would only reset my custom action I guess. If my graph would use built-in actions or actions which require a return value, the graph would still be broken, or not?

    Maybe not, because I did some further testing: It seems that the Finish Action is not reset properly because it stops the graph during execution of that action. If I manually reset all nodes (as done in Graph.Stop) before I start the graph again everything looks fine.
    So, the EndAction(null) call might be the fix because it enables my Finish action to be reset.
    Can you confirm this guess?

    #15127
    Gavalakis
    Keymaster

    Hello again,

    The EndAction(null) is a special EndAction call used when we want to interrupt the action and reset it completely. It is also used from within nodes like Behaviour Tree Action Node; when the node resets it calls EndAction(null) to interrupt the action and reset it, since in these cases we do not care about success or failure (this is why manually resetting all nodes afterwards also resets the action). So is the same case when the graph is to be stoped from within the action, meaning that we do not care about whether the action ended in success or failure. We just want to end and reset it. Thus in these cases, the special call EndAction(null) can be used.

    Please let me know if this information helps.
    Thank you!

    Join us on Discord: https://discord.gg/97q2Rjh

    #15129
    hosnkobf
    Participant

    Hi,

    Unfortunately, your reply doesn’t answer all my questions.
    What I was not sure about is not about my particular action but all actions in the graph.

    So, when I call graph.Stop() within an action it seems that all actions of the graph are reset except the one or ones which are currently executed. (Is this correct?)
    Therefore, I have to reset the current action manually by calling base.EndAction(null).
    But is this enough? Even if non-active-actions are properly reset what about other running actions when using a parallel composite node? I guess there could be actions which are also still running but I cannot call EndAction(null) on them because I don’t know about them. So, I believe they would not reset and would keep running also during the next time I use the graph instance…

    #15130
    hosnkobf
    Participant

    I did some tests but my suggestion turned out to not being true.
    It seems that other running actions are reset properly.

    But I found another bug: The composites are not reset. The sequencer containing my Finish-Action was marked Success (although i ended with null and not true) and at the second run just did not do anything anymore.

    See the attached pictures for more information (the pictures are both from the second run).

    EDIT #1:
    When on the second run the left part has finished (61 seconds waiting time are over), the graph restarts and the right part is also run again.

    EDIT #2:
    If I reset the graph again manually every time before I start it everything seems to work.
    I use this code:

    I am not sure if this also works with sub-graphs though.

    Attachments:
    You must be logged in to view attached files.
    #15147
    Gavalakis
    Keymaster

    Hello again,

     

    You are right. This is why the included action for stopping the behaviour (the action task called Control Graph Owner), does EndAction(null) andgraph.Stop()` after 1 yield frame. If you want to do the same in your custom action, here is how you could do it:

    Doing this will solve the issue where the sequencer (and other nodes in general) are not resetting correctly. Once again, the problem and special case here, is the fact that the graph is stopped from within its own execution. Stoping the graph otherwise (outside of its own execution does not need any of this).

    Please let me know if the above works for you.
    Thanks!

    Join us on Discord: https://discord.gg/97q2Rjh

Viewing 7 posts - 1 through 7 (of 7 total)
  • You must be logged in to reply to this topic.