Tick() broken for non-repeat graph without actions running over time

NodeCanvas Forums Support Tick() broken for non-repeat graph without actions running over time

Viewing 10 posts - 1 through 10 (of 10 total)
  • Author
    Posts
  • #13687
    clem
    Participant

    Hi,

    Updating Node Canvas to the latest version broke my existing logic and I’ve been digging into what happens.

    My setup is very similar to the section in the documentation called “Manual Tick (BehaviourTrees only)”
    – I instantiate a BehaviourTreeOwner at runtime
    – I set its “behaviour” property to the behavior I want (obtained via inspector variable)
    – I set it to not repeat
    – Then I call Tick() on that owner from Update

    What seems to happen is that my graph is never technically running, since I don’t start it, and it executes in one frame (it doesn’t contain running actions, all actions it contains return Success right away).

    The updates to BehaviourTree.cs and BehaviourTreeOwner.cs that I can see from my previous version and the latest one seem to no longer directly call Tick on the behavior but instead use UpdateBehaviour. However, this leads to a check if graph.isRunning == true before actually calling GraphUpdate(). Since my graph is not runnning, this check fails and it will never actually update the graph when I call Tick().

    Could you please either provide a fix for this, or let me know what the new correct way of achieving that result is?

    My code is

    Thank you

    #13696
    Gavalakis
    Keymaster

    Hello,

    Thanks for finding and letting me know of this bug.
    A quick fix/solution to that (in the latest version), would be to make a call to “StartGraph” with the parameter “autoUpdate” being false in your Initialize method. In that same ‘StartGraph’ overload that takes the “autoUpdate” parameter, you can also provide a callback for when the behaviour is finished. You can if you want use that callback to also stop the graph when that is done.
    Here is an example code:

    Please let me know if that works for you.
    Thank you!

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

    #13782
    clem
    Participant

    Thank you, for now I just commented out the check for IsRunning as I’m not using graphs extensively and don’t have any graphs that will run more than a frame so it won’t break anything yet.

    I believe I’ve tried something similar to what you suggest while playing around and looking into the source code, but since my graph stops right away, starting it just gives me one frame of execution before it’s no longer running again. I noticed that adding a node that runs over multiple frames (e.g. a debug log for 2 seconds) would allow the graph to update for those 2 seconds then stop.

    I’ll leave it like that until my next update and hopefully by then a better fix will have been released for this use-case. Thank you

    #14083
    clem
    Participant

    Hello again!

    I updated to the latest version of NodeCanvas and the problem is back so I have to repeat my local hacky fix again, and figured I’d point out the issue once more in hope for an official fix.

    Here’s how I’m using Node Canvas:

    • I control my player character with a Behavior Tree so I can visually organize what to do based on conditions (e.g. is the player trying to move, is the movement allowed, etc.) not necessarily because this makes more sense than hard-coding player logic but because that way all actors in the game, whether AI or players, follow the same structure and I can share modules between them.
    • At the moment, that BT controlling my player does not actually run any actions for longer than a frame. For instance, it determines what forces to apply or what direction to move to, but does not enter an action that completes later, and so the BT ends the frame it is called.
    • My actor setup is fairly advanced, so I want the BT to be called after a lot of other scripts have ran (e.g. sensing the surroundings into data that can be used for determining what to do this frame) and before others do (e.g. kinematic physics calculations) so I want to call it manually at a specific point each frame with Tick() (not to set it to repeat automatically)

    This used to work just fine when I initially created this setup, but after upgrading NodeCanvas a few months ago, it is no longer executing my BT each time I Tick() it, only once the first time.

    In CanvasCore/Framework/Runtime/Graph/Graph.cs, I have to remove the check for isRunning == true in the UpdateGraph function to make my BT work, as a graph that doesn’t start any longer-than-one-frame action will apparently only “run” for one frame, and so Tick() will not execute it past the 1st frame (where it actually starts and gets executed once).

    You suggestion from a few months ago does not help, the graph still isn’t considered to be running after the initial frame it ran and completed on, so Tick() does nothing.

    Repro steps:
    – Create a new project
    – Import NodeCanvas
    – Create a new GameObject
    – Add a Behaviour Tree Owner to that object & set it to not repeat and do nothing on Enable/Disable
    – Create a bound BT for that owner that simply logs a variable value from the blackboard
    – Create a MonoBehaviour on that same object that contains the following code:

    What happens:
    – The value of the blackboard variable is logged once

    What I expect:
    – The value of the blackboard variable is logged each frame

    This would work:

    but means it won’t work for any graph that lasts more than one frame.

    Could you look into this issue please, and either support that functionality again, or let me know of an alternative supported way to achieve that result?

    I guess the old Tick() behavior was “start or update” and the new one is “update if running” which is causing my issues. I’d just like to be able to update NodeCanvas without having to reapply fixes each time to maintain the functionality of the NodeCanvas version I started my project with.

    Thank you

    EDIT:
    I guess I was a bit caught up on making sure Tick() worked like it did before, I can do this I guess:

    Let me know if you see any issues with that approach, thank you

    Attachments:
    You must be logged in to view attached files.
    #14576
    soren bach
    Participant

    Yeah, I came here to say I have the exact same problem. Why has this not been fixed yet? :\ I’m using the latest version from the asset store (2.9.6).

    For now I’m using the fix that Clem posted.

    #14579
    Gavalakis
    Keymaster

    Hello,

    Aparently I completely missed Clem’s last post. I am really sorry about that!

    Tick() should always be called after a graph is Started (regardless of whether or not the behaviour is repeated). StartBehaviour must be called since it is responsible for setting references as well as calling various callbacks in nodes like OnGraphStarted (which are essential for correct initialization).

    If we want to manually Update a graph (or Tick a tree in case of BT), we need to call StartBehaviour with the autoUpdate argument set to false owner.StartBehaviour(false, null);.

    In cases where we manually Tick the tree, leaving the “repeat” option enabled is desirable, since the point of the “repeat” option is to automatically Stop() the tree (disable it). Thus if we do not want any automation like that, we need to keep the “repeat” option enabled.

    As such, to manually Tick() a tree correctly, all we have to do is leave the “repeat” option enabled and do something like this in code:

    I have just updated the documentation (which was missing the part that StartBehaviour needs to be called). I have also now added a warning if UpdateGraph is called without first having the graph started to avoid any confusion.

    Please let me know if this works for you.

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

    #14584
    soren bach
    Participant

    Hey, thanks for getting back to this. I’ve tried implementing your way, but I’m getting some odd behaviour. This could be because of my own AI logic though, so I’ll have to investigate.

    But when I’m using your implementation, I’m getting a few warnings that doesn’t seem to lead back to any of my code?

    #14585
    Gavalakis
    Keymaster

    Hey,

    You are welcome.
    In the BehaviourTreeOwner inspector, you need to set the “OnEnable” setting to “Do Nothing”. Otherwise if it is set to “Start Behaviour”, the behaviour will be started automatically as normal and by default. However if in your case you want to start the behaviour manually (like the code provided) you don’t want the BehaviourTreeOwner to also start it. Thus setting “OnEnable” to “Do Nothing” will prevent this 🙂

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

    #14587
    soren bach
    Participant

    Worked like a charm, thank you 🙂 !

    #14589
    Gavalakis
    Keymaster

    You are very welcome 🙂

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

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