November 27, 2022 at 4:22 pm #5666
I’m trying to insert a brief pause in my NPC’s behavior.
At the moment, I’m using a behavior tree to go through a scripted series of move to a location then perform some action (pickup, operate or drop an item).
To simulate my character operating the item (we don’t have any animation to visualize this at the moment), I wanted to have a simple pause so I inserted a Timer node and gave it about 3.0 seconds. An example of what it looks like in my tree:
CONSTRAINT (id == 3)
Custom Move action (Repeat: Until Success)
Custom Action (Repeat: Never) (One off to operate the item)
Timer (Seconds: 3.0, Returns: Success)
Expression (Returns: Evaluate) id == 4 (set for next location)
When I select my NPC and watch the visual debug, the Timer node reports running (yellow) and goes well past the 3 seconds that I set.
At one point I made a change in the Seconds value (set it to 2.0 for example) and then my NPC moved on to the next item in the Sequencer and was able to move onto the next location. NOTE: I made this change while the tree was actively running.
Should I include a timer node in that sequencer differently? Is there some bug with Timers?
November 27, 2022 at 7:21 pm #5672
- This topic was modified 2 years, 2 months ago by Aaron Mueller.
The timer node is not the problem. If the timer node looks like it is constantly running, it is almost certainly because the SEQ is repeating itself. In your example, what would ever cause your final expression to return true?November 28, 2022 at 12:27 am #5674
The final expression was a typo. That should say “=” not “==”. Sorry about that.
In my case, assigning id = 4 will cause the id == 3 constraint to fail and the NPC to move from one place to the next just fine, except when I have a Timer node as one of the children in my Sequencer.
NOTE: One point of clarification, the id value is checked in Constraint nodes which are children of a Selector.
1) I switched the Returns value on this particular expression node from Evaluate to Success. No difference.
2) I checked Pause When Hit on the Timer node and the NPC moves to the location and pauses. Hitting the pause button, immediately causes Unity to pause again.
3) I unchecked Pause When Hit on the Timer node and hit pause. Unity unpauses and the NPC stays in the same spot animating a walk cycle in place.
4) In the live running tree, I edit the Seconds value and set it to 0, the NPC immediately begins moving to his next location.
5) I tried moving the timer to the end of the Sequencer (swapped Expression and Timer node positions). There is no pause at all (likely because now the Constraint “id == 3” fails).
6) I tried moving the Timer node between my Custom Move and Custom Action (to manipulate the item). I get same behavior as #3 and performing #4 gets the NPC moving along again.
7) I tried replacing the Timer node with the the following:
PAR (Repeat: Until Success) Suceed: Any Fail: All
— Animate (Repeat: Forever)
— Timer (5.0 s) (Returns: Success)
Results are the same. I still get a Timer node that behaves like it is running forever. Setting the Seconds to 0 gets the NPC moving like in #4 above.
So, what exactly am I doing wrong here? I’m stumped.
November 28, 2022 at 3:18 pm #5680
- This reply was modified 2 years, 2 months ago by Aaron Mueller.
Set a pause not on the timer but on the custom action. After that action completes and the timer starts running, see if you continue to pause on the custom action.December 2, 2022 at 3:50 pm #5717
Per your suggestion, I checked “Pause when hit” on my custom action. It pauses and continues to pause on my custom action.
My custom action was set to Repeat: Never and in the Behavior Editor during visual debugging it shows Green so that it has reported SUCCESS in the previous tree tick. Does the BT actually go through children that have previously reported SUCCESS to their parent node? I thought that upon the next tick of the tree, the child node that reports RUNNING is the node that it would return to.
Looking at the code that I’m calling in the Custom Action, it checks things in the Unity Update() method, so I have to guess that it calls across multiple frames. If i set the expression field to 0 for the time, it goes right through the timer node with no issue. So, why does it “hang” when I put a value? This makes little sense to me.
My custom action calls 4 lines of code and then returns SUCCESS. If on each tick of the tree the Constraint node that returns RUNNING goes through each child until it hits the RUNNING Timer node, it will always “Pause when Hit” when it gets to my Custom Action. And since it returns SUCCESS (and appears as green), I’m not sure what that proves.
If I check “Pause when Hit” on the RUNNING Timer node, it stops on that one as well. If I clear that and put it on the last child node (Expression), I never hit it since the Timer is reporting as RUNNING still (showing yellow highlight in the Behavior Editor while visual debugging).
Any other suggestions? This doesn’t make sense, but then I may have a bug in my understanding of Behavior Trees and RAIN still.December 2, 2022 at 4:19 pm #5722
If your custom action is getting hit every frame (which the pause indicates) then your Sequencer is starting over every frame. Something outside the Sequencer is causing that to happen (because the sequencer is pausing on the timer).December 2, 2022 at 4:22 pm #5723
I am not sure if this helps, but my purpose of the timer was to be a delay which represents an amount of time that the NPC would be operating the equipment. Ideally, I’d have a way to visualize this with an animation, but I don’t have the custom animation available at the moment.
I tried just putting a basic animate node in before my custom action (tried both Repeat: Until Success and Repeat: Never) and my NPC never stops playing the walk in place animation and never seems to move on to the next node.
Would it be possible to move the “delay” into my custom action? I wasn’t really sure the best way to tackle this. I had tried to do some form of countdown, but that didn’t seem to work either.
The code called in the custom action causes an event to be fired. I guess in one way, it would be ideal to not return SUCCESS until that event was caught. I will have to investigate this option a bit further.
December 2, 2022 at 4:27 pm #5728
- This reply was modified 2 years, 2 months ago by Aaron Mueller.
The animate action will continue to repeat forever if you are playing a looping animation. Usually if you want that to play for some time and stop, you would use a parallel set to succeed on any, and then pair it with a timer.
Yes, you could move the delay into your custom action. You just need to set a timer on Start (equal to your delay time + ai.DeltaTime) and then reduce the timer on every execute (subtract ai.DeltaTime). When it hits < = 0, you can exit.December 2, 2022 at 4:28 pm #5729
By “set a timer” I mean create a variable to hold the countdown and then decrement it on each Execute.December 2, 2022 at 4:35 pm #5731
I didn’t check but I suspect that it is in fact set to Loop in the Animation Import settings. I think I force them to not loop in my randomly choose an idle action. D’oh!
I’ll give the other option a try with setting a variable and decrementing.
Thank you.December 2, 2022 at 6:17 pm #5734
Using your suggestion of the timer and decrementing by ai.DeltaTime, I was able to get something working. It’s not perfect, but for now it will suffice until I can come up with animations that support the NPC operating the item held.
I’d sure like to understand why the provided Timer node doesn’t seem to behave as I expected (or to understand why my expectation may be wrong). But for now I can work with this.
Thanks again.December 2, 2022 at 8:23 pm #5741
As I’ve said, the Timer node is absolutely (a) working correctly and (b) not the problem. The problem with your tree is that the Sequencer which contains the timer is restarting constantly. I’d have to see the broader behavior tree/context to understand why.December 2, 2022 at 9:15 pm #5742
So, should the Sequencer be marked as Repeat: Unitl Success? I originally had them all set to Repeat: Never which would explain why the node keeps restarting (at least, as I understand based on your feedback), but as a test I set the first one with the Timer node to Repeat: Until Success and that didn’t appear to change anything.
Unfortunately, I am unable to provide any screenshots and the project is simply way to large to send (nor am I allowed to anyway). Would it be ok to email Jester and I’ll diagram the entire tree structure for him to pass to you? Perhaps if you see the current structure it will be more apparent where I’m going wrong.December 2, 2022 at 9:56 pm #5743
I don’t think repeating the Sequencer is the solution. The sequencer itself doesn’t seem to be failing. Instead, something outside the sequencer (some containing node) is either failing or succeeding, causing the Sequencer to start and restart on the next frame.
Sure - if you have any additional info you can send over via Jester, that would be helpful. I don’t actually need the entire project, nor do I need any code. Just the BTAsset itself would be sufficient so I could see the structure of the tree.December 2, 2022 at 10:04 pm #5745
Unfortunately, I don’t have an easy way to do this. The computer I have email on is not the one I’m posting this reply to. I’ll have to reproduce in writing the structure for you, sorry. Not trying to be difficult but I have limited options.
I have brief pauses now which I’m living with. I have used your helpful reply to me about making an Expression so that it shows up in the Behavior Editor. I use that field to set the time in conjunction with your other suggestions.
At the moment, I’m trying to work on getting away from using the id with a Selector node. Due to the way I’m modifying the id (using an Expression node), it’s behaving like a Sequencer. I’m trying to come up with a way to allow variation on which items the NPC will go for. I’ll explain more in my email. Again, thanks for your patience and assistance. I appreciate it.
You must be logged in to reply to this topic.