Help with optimizing tree

Ormy

New member
Hey! I'm making a VR hunting game with animal behaviors. So far I've gotten most working that I need but my behavior trees are really heavy when there are multiple animals / herds rendered. BehaviorManager.Update can be over 20ms which alone is more than VRs budget and I'd like to ask what are some good ways to optimize trees for performance? Thank you!
 
If you deep profile your project where is the bottleneck? My guess is that one of the tasks that you are using is taking up the majority of the time.
 
I was checking animals senses parallel in every frame (can see player, can hear and within distance for smell check) and if I removed that, it became really light. Was thinking to set behavior manager to manual and call ticks from code when needed instead of constantly checking it. Didn't run deep scan yet but I can do so tomorrow and report back! Just wanted to know if there are some general good rules to follow if you need to check multiple things at once like I need here for the senses.
 
behaviordeepprofile.png

Ran the deep profile and as I thought, it ticks canhear, cansee and within distance and those ticks eat all the performance. I use those to check if player is nearby and then run their own trees where I set animal to different stances if they see, hear or smell the player.

Here is my current tree before I start modifying it:
WanderScreenshot.png

There might be too many repeats too but I couldn't make it work properly without them. I need to check all the parts in case animals stance changes and it should react properly. Flee is the highest priority and should interrupt everything else if animal is set to flee stance. Then sense checks are in the middle going through if player is seen, heard or within distance to be smelled. If those pass, they will run their own trees where basically same checks are again for each stance (calm, nervous, alert) and change animals stance accordingly. Reacting to callers is next, making animals come to a caller if they hear one. Then check if animal is stuck and in flee and make them run with wander on for sometime to get unstuck and set isStuck back to false so it can return to normal. And lastly checking if animal is in herd or not and running the appropriate wander. Inherdwander is normal wander but all the animals in the same herd shares destination and picks a random spot around that, making them move together.

I've used the behavior designer for the past 2-3 months to make this tree so it might be done wrong or not as efficient as it could. That's why I thought running the sense checks from script when certain criterias are met might be better in this case. We can have tens of animals visible at ones if couple big herds happen to walk into the same area. Any improvement ideas would be greatly appreciated :)
 
I do think that if you can reduce the number of parallel tasks then that will help. Have you seen this tree? I think that if you reduce the number of parallel tasks to just being the bulk of the active logic then you'll improve your performance. As an example if flee is the highest priority, then immediately under your topmost Selector you'd have the flee branch as the leftmost branch which is reevaluated with a lower priority conditional abort. Try to reduce the number of tasks that are reevaluated as well. A self conditional abort is fine as that only runs when the child branch is running, but a lower priority branch is more performance intensive as it will reevaluate when a lot more of the tree is active.
 
I do think that if you can reduce the number of parallel tasks then that will help. Have you seen this tree? I think that if you reduce the number of parallel tasks to just being the bulk of the active logic then you'll improve your performance. As an example if flee is the highest priority, then immediately under your topmost Selector you'd have the flee branch as the leftmost branch which is reevaluated with a lower priority conditional abort. Try to reduce the number of tasks that are reevaluated as well. A self conditional abort is fine as that only runs when the child branch is running, but a lower priority branch is more performance intensive as it will reevaluate when a lot more of the tree is active.

Thank you! Nice to know that I had the right idea at least. I changed the manager to manual and moved senses to their own trees which I tick from code every second or so if animal is rendered and close enough to the player. Eliminates unnecessary checks if animal is not even visible or outside of their best senses range. I'll then run just wander and flee on that main tree. I even managed to remove animals smell completely from the tree since it was done from code anyway. Seems to be lighter already. I've been following that tree you linked and it's been my base reference the whole time now. Still pretty complicated for my first behavior tree but hope I'll manage :D
 
Moved two of the senses to code / manual ticks and I can't even see behaviorManager.Update or Tick in the profiler at all anymore. Seems to work super well so far! And moved flee as you suggested so that helps to and it works better than before. So excited to work more on this! :D
 
Top