Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Behavior Designer - Behavior Trees for Everyone

Discussion in 'Assets and Asset Store' started by opsive, Feb 10, 2014.

  1. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    Hi,
    Quick perf question. I'm getting a pretty big perf hit with only a few behavior trees active (there are a crapton of disabled objects with behavior trees on them as well)

    With about 6 active behavior trees I'm getting a 1.11 ms cost. Of that:
    .57ms is "PopTask" with "SaveResetValues" one of the more expensive tasks.
    upload_2016-12-18_18-6-55.png

    Also within "Run Parent Task" Pop task is also a big hit on performance:
    upload_2016-12-18_18-9-36.png

    Anything I can do to get this number down?


    Here are the behavior trees I'm running:
    3 of these. (and many disabled)
    upload_2016-12-18_18-11-8.png
    2 of these
    upload_2016-12-18_18-11-54.png
    (sub tree of the above)
    upload_2016-12-18_18-12-14.png

    And one more simple tree.

    Any thoughts what would be causing such a huge performance hit?

    Thanks.
     
  2. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    Restoring the saved values uses reflection so the way to get the absolute best performance would be to save and restore the values manually without using reflection. Unfortunately there's not an automated way to do that. Once you get that line down lets see what the profiler looks like.
     
  3. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    Ok great thanks!

    Could I ask at a very high level what is causing values to be saved/reset? E.g. switching a node? Restarting the entire tree? Simply setting a shared variable? I don't have "Reset values on restart" checked but I may be doing something really dumb. E.g. Maybe "Is Alive" is getting saved/reset every frame due to the way I set conditional aborts up.

    Also what values are being saved/Reset?
    The "Shared" variables?

    Thanks for taking the time, I know a bunch of questions can be a pain in the butt. :)
     
  4. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    Double check that Save Value On Reset isn't checked - this is what will trigger it when the tree is reset.
    All of the public fields.

    No worries :)
     
  5. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    Heya,
    I did have 1 behavior tree with Save Value On Reset checked. Unchecking that saved me about .6ms.

    Most of the remaining MS is in RunParentTask(). Am I correct that that would be called due to conditional aborts? If so I may be able to save some perf by changing the structure a-bit.
     
  6. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    If you deep profile you should be able to see exactly what the cause is - RunParentTask doesn't do much so chances are it is something with your actual task causing the slowdown.
     
  7. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    So I tracked this down, thanks again for the help.

    The overhead was almost 100% pop and push on the behavior trees. I shorted the trees out with a bool check to force the tree to restart over and over and got the same ms hit.

    That said turns out the scene I was in didn't have a Behavior Manager in it. So with 3 trees active hitting a fail and restarting every frame this added up to .4 ms. Oddly with the Behavior Manager telling the trees to only run every .2 seconds I don't even get a .4 ms hit every .2 seconds and everything is wonderful.

    So everything is good with me. Thanks again!
     
    opsive likes this.
  8. ZX8888

    ZX8888

    Joined:
    Dec 21, 2016
    Posts:
    3
    Heya,
    I have a trouble about the Conditional Abort.When I have some Conditionals in a Lower Priority Abort Type Sequence,It don't work well.I want all of Conditionals return success then abort the running task,but in fact it happen when one of Conditionals' status changed,can I make the Conditionals to a Conditional List? how to do?
     
  9. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    Can you post your tree as well as point out the specific branch that you are looking at? Conditional aborts will trigger when any status changes, not only going from failure to success.
     
  10. ZX8888

    ZX8888

    Joined:
    Dec 21, 2016
    Posts:
    3
    tree.png
    Wait was interrupted When Conditional1 change status.I want use Conditional1、Conditional2 and Conditional3 as a
    composite Conditional.What should I do?
     
  11. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    If you don't want the abort to trigger at all then you'll need to join the three conditional tasks into one. It is an interesting idea to have a grouped conditional task though and I've written the idea down to take a closer look at.
     
  12. ZX8888

    ZX8888

    Joined:
    Dec 21, 2016
    Posts:
    3
    Thanks.If you provide a Composite Conditional,we can combine the existing Conditionals conveniently.
     
    Last edited: Dec 22, 2016
  13. Amitloaf

    Amitloaf

    Joined:
    Jan 30, 2012
    Posts:
    97
    So I did as you said, but it doesn't always work. For example i have this tree (attached)
    As you can see it's stuck on "Running" and the input action on the top right doesn't run even though it's parallel.

    Also (the weird thing) On the first time I start "Running", instead of stopping it just goes on to the next task in the tree (although it's governed by a selector) - activating a breakpoint on it prevents it for some reason and makes it stay and get stuck in the aforementioned position (running the same task over and over without going on the Input Action task).

    And yes, I just updated to the last version.
     

    Attached Files:

    Last edited: Dec 22, 2016
  14. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    It looks like your Input Action returns success, correct? If you want it to continuously run you'll either need to add a Repeater to the top of it which repeats forever or have it return a status of running.
     
  15. xxhaissamxx

    xxhaissamxx

    Joined:
    Jan 12, 2015
    Posts:
    134
    does it have way to avoid other agent (AI don't push other AI to reach the target) ?
     
  16. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    Behavior Designer is purely a behavior tree implementation so it does not do any pathfinding. With the Movement Pack it can use Unity's NavMeshAgent, Apex Path, or A* Pathfinding Project to move the agents but it is then up to the underling pathfinding implementation to actually move the agents. To answer your question though, the NavMeshAgent and A* Pathfinding Project does allow for dynamic obstacles. Apex Path requires their Apex Steer addon.
     
    xxhaissamxx likes this.
  17. Amitloaf

    Amitloaf

    Joined:
    Jan 30, 2012
    Posts:
    97
    you are correct but if I put a repeater on it (or running), the minute the big tree returns success, it stops doing anything but running the input command. Does that mean I need to put a repeater on the big desicion part of the tree as well?

    If I understand correctly "Parallel" just runs all Running subtrees until one of them returns success and then continues running the other Running subtrees until either stopped or all of them return success. Am I correct?
     
  18. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    Yes, that's right.

    Parallel will stop running as soon as one of the child tasks return failure or the entire tree is stopped. If you want a parallel task to return as soon as the first task returns success you can use the Parallel Selector (though I don't think you want that in this case).
     
  19. xxhaissamxx

    xxhaissamxx

    Joined:
    Jan 12, 2015
    Posts:
    134
    thanks for answer
     
  20. FlyTroll

    FlyTroll

    Joined:
    Jul 20, 2014
    Posts:
    8
    Hi
    How i can playing "Idle" animation when we stoping and waiting when move to next waypoint (Waypoint Pause Duration) in Patrol mode ?
    Thanks
     

    Attached Files:

  21. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
  22. Amitloaf

    Amitloaf

    Joined:
    Jan 30, 2012
    Posts:
    97
    Yes but if a task in Parallel is returning success, it will stop running until the whole parallel is ended, right?
     
  23. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    That's correct, the parallel task will complete with success as soon as all of the children have returned success. It will return failure as soon as the first child returns failure.
     
  24. SoulSpectrum

    SoulSpectrum

    Joined:
    Nov 4, 2016
    Posts:
    5
    I'm a little confused on how to apply this to animations still, the site you that's mentioned and archived is down as well from your earlier post about playing animations. I'm super excited to choose this over the AI systems cause of the flexibility. The mechanims I have are using variables and booleans to change and transition between animations.

    How can the behavior graph be used to modify variables within a controller?

    Lastly, I'm wanting to do groups of AI together that can spawn, if I were to perhaps clone new units how can I have the behavior reference themselves for Target Game Objects?

    I have a theory on one way of doing it but with your system I feel like this isn't efficient since I don't know how one can self reference. Using a C# script with public variables for something like Death, Speed, Jump. The script is always running a update to the anim object using the public variables. The variables can be modified using the "Set Field Value" to get an object (but how can you self reference your own?), connect to the component script, then one of the public variables, and modify it from there.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class AnimationHandler : MonoBehaviour {
    5.  
    6.     Animator anim;
    7.     int speedHash = Animator.StringToHash("Speed_f");
    8.     int animationintHash = Animator.StringToHash("Animation_int");
    9.     int deathHash = Animator.StringToHash("Death_b");
    10.     int jumpHash = Animator.StringToHash("Jump_b");
    11.     int crouchHash = Animator.StringToHash("Crouch_b");
    12.     int weapontypeHash = Animator.StringToHash("WeaponType_int");
    13.     int groundedHash = Animator.StringToHash("Grounded");
    14.     int staticHash = Animator.StringToHash("Static_b");
    15.     int deathtypeHash = Animator.StringToHash("DeathType_int");
    16.     int meleetypeHash = Animator.StringToHash("MeleeType_int");
    17.  
    18.     public float Speed = 1;
    19.     public int AnimationType = 0;
    20.     public bool Death = false;
    21.     public bool Jump = false;
    22.     public bool Crouch = false;
    23.     public int WeaponType = 0;
    24.     public bool Grounded = true;
    25.     public bool Static = false;
    26.     public int DeathType = 1;
    27.     public int MeleeType = 1;
    28.  
    29.     void Awake () {
    30.         anim = GetComponent<Animator>();
    31.     }
    32.  
    33.     // Use this for initialization
    34.     void Start () {
    35.    
    36.     }
    37.    
    38.     // Update is called once per frame
    39.     void Update () {
    40.         anim.SetFloat (speedHash, Speed);
    41.         anim.SetInteger (animationintHash, AnimationType);
    42.         anim.SetBool (deathHash, Death);
    43.         anim.SetBool (jumpHash, Jump);
    44.         anim.SetBool (crouchHash, Crouch);
    45.         anim.SetInteger(weapontypeHash, WeaponType);
    46.         anim.SetBool (groundedHash, Grounded);
    47.         anim.SetBool (staticHash, Static);
    48.         anim.SetInteger(deathtypeHash,DeathType);
    49.         anim.SetInteger(meleetypeHash,MeleeType);
    50.     }
    51. }

     
    Last edited: Dec 30, 2016
  25. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    I just tried the cached version and it looks like it's working now:

    https://web.archive.org/web/20160317180801/http://mecwarriors.com/2014/12/09/navmesh-and-mecanim/

    Looking at your animator controller specifically, I wouldn't have each animation type as its own layer but instead use substates. If each animation has its own layer then you'd have to manage the layer weights and it would become unnecessarily complicated.
     
  26. SoulSpectrum

    SoulSpectrum

    Joined:
    Nov 4, 2016
    Posts:
    5
    Alright, thanks for the advice but what about the second part of my question? Regarding referencing the object with the Behavior Component so I can create groups of units patrolling. Some variables using a game object don't let me have that option and I have to connect it manually. I may be looking over a setting or node to answer this but idk where
     
  27. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    If you leave the Target GameObject field empty then it'll automatically reference the current GameObject for most tasks. This should then allow you to clone objects and have the correct reference.
     
  28. SoulSpectrum

    SoulSpectrum

    Joined:
    Nov 4, 2016
    Posts:
    5
    Alright, thank you so much for the quick responses. Its encouraging to know there's active support behind this product unlike do many others. I'm sure I'll have a lot of other questions once I start working with it but right now I really only have one important question.

    Is this functional for mobile development? Like is there anything specific I'll have to do for the work processes or use less of some features of when it comes to handling the FPS? We're doing the project across PC and mobile platforms.
     
  29. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    Yes - I recommend keep profiling it to look for potential bottlenecks. Traversing the tree is extremely fast - in general if there's an AI-related bottleneck it deals with some intensive logic within the task rather than the tree traversal iteself.
     
  30. xxhaissamxx

    xxhaissamxx

    Joined:
    Jan 12, 2015
    Posts:
    134
    is there way to send data to tree like
    GetComponent<BehaviorDesigner>().SetInt("myIntName",5);
     
  31. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    xxhaissamxx likes this.
  32. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    Gamekakkak recently released an integration with Behavior Designer and ORK!



    You can get it on the Asset Store on this page.
     
    xxhaissamxx likes this.
  33. chaneya

    chaneya

    Joined:
    Jan 12, 2010
    Posts:
    416
    Opsive,

    I have another editor request for the next version. This is something that drives me crazy. Can you have SharedList variables closed or folded by default in the variables tab of the Behavior Designer Editor or better yet have them remember your previous selection (Folded or Unfolded). I use quite a few SharedLists in my Trees and right now I am in a running battle closing the lists so I can see the rest of my variables but every time I press Play, they are unfolded again taking up a ton of vertical real estate in that variables tab. Basically it's impossible to keep SharedList variables folded or closed. And for some reason, going into Play mode causes the sharedLists to default back to an unfolded state.

    Thanks
     
    Last edited: Jan 20, 2017
  34. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    The foldout preferences aren't serialized so that's why they change state when you enter/exit play mode. I have a method now to save the state and I'll include it in the next version.
     
  35. HiThatGirl

    HiThatGirl

    Joined:
    Nov 12, 2014
    Posts:
    19
    QQ截图20170123171406.png QQ截图20170123171021.png QQ截图20170123171236.png



    The Trigger Why no work?
     
  36. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
  37. chaneya

    chaneya

    Joined:
    Jan 12, 2010
    Posts:
    416
    Opsive,

    Just a general question:

    Have you been working with the Unity 5.6 Beta that contains the new Navigation system? I'm assuming many Behavior Designer tasks (Movement etc) will be upgraded for the new Navigation system and I'm just looking for your thoughts on how much work it will be to implement into existing projects that use Behavior Designer.
     
  38. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    I've only briefly looked at the 5.6 beta so far, but it looks like it'll just require some API updates. I've seen a video where somebody had 10 or 20 agents circling around a sphere using the new NavMesh so that was pretty cool. It also means that the addon packs won't require much updating.
     
    Last edited: Jan 24, 2017
  39. TheButterBeeCrew

    TheButterBeeCrew

    Joined:
    Nov 25, 2016
    Posts:
    10
    Hi, Opsive. I have 2 questions about how to use the tool.
    1. I tried to use the Seek task to move a capsule to a target position, but the capsule never moved and that task was completed successfully right away. I followed your overview tutorial video to do it. The Can See Object task was able to see my target object and followed it when I placed my capsule close to the target object, but just when I move the capsule further, it won't move to the target position in order for the capsule to see the target object. Do you know why?

    2. If I want to have my prefab patrol around the scene by using its Walking animation, is the right way to do it would be having a Sequence task connect to a SetTrigger task to set the walking animation trigger active and a Patrol task?

    Thanks.
     
  40. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    Are you getting any errors? In cases like this the most common reason is because the navmesh hasn't been baked yet.

    https://unity3d.com/learn/tutorials/topics/navigation/navmesh-baking
    Take a look at this page on syncing animations:

    http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=135
     
  41. TheButterBeeCrew

    TheButterBeeCrew

    Joined:
    Nov 25, 2016
    Posts:
    10
    1. I did get an error first, but then I went to bake the navmesh. The error was gone but then the capsule still wasn't able to seek to the target position. What happened was that instead of returning success after the capsule seek to the target position, the Seek task execution in the behavior tree returned success right away after I hit play. Do you know what might caused that?

    2. I will take a look the article. Thanks!
     
  42. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    What does your tree look like? The definitive way to determine why it returned success would be to place a breakpoint within Seek.OnUpdate and see the conditions that caused it to return TaskStatus.Success, but I may have an idea based off of your tree.
     
  43. TheButterBeeCrew

    TheButterBeeCrew

    Joined:
    Nov 25, 2016
    Posts:
    10
    I'm remote now so I can't get a snapshot of the tree, but it looks the same as what the overview tutorial video on your site (http://www.opsive.com/assets/BehaviorDesigner/videos.php?id=2) shows. A entry follows by a seek task. I replicated every step from tutorial, but mine didn't work.

    I then tried the following which also showed in the overview video:
    Selector
    | |​
    Sequence Seek
    | |​
    Can See Object Seek
    The above tree works when I put the target object within the capsule's view distance when play, the capsule will seek to the target object. However, if the target object is not in the range of the view distance, the execution will go to the seek task on the very right when play and return success right away without seeking the target position that I set.

    I will try to debug it with your instructions later.
     
  44. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    It sounds like it may be related to how you have conditional aborts setup. Here's a post with a working example similar to what you're going for:

    http://opsive.com/forum/index.php/topic,41.msg518.html#msg518
     
  45. TheButterBeeCrew

    TheButterBeeCrew

    Joined:
    Nov 25, 2016
    Posts:
    10
    Thanks.

    But what about the problem with my first tree: entry -> seek? I expected it should work just the same as the tutorial video shows which the capsule will move to the target position and then return. I believe this tree does not involve the conditional abort configuration right? It simply just failed to move the capsule to the target position. I will debug it to see what happen but if you have any idea about this one, let me know.
     
  46. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    You are correct in that you don't need any conditional aborts with just a seek task. In that case I would verify that you aren't getting any errors related to the NavMesh/NavMeshAgent. When you get errors all bets are off as to what it is going to do because that execution thread is in a bad state. The page that I linked to will also help with a working example that you can play with.
     
  47. TheButterBeeCrew

    TheButterBeeCrew

    Joined:
    Nov 25, 2016
    Posts:
    10
    OK. I will double check. Thanks for your help today.
     
  48. Duffer123

    Duffer123

    Joined:
    May 24, 2015
    Posts:
    1,215
    @opsive ,

    How can you pull data and variables or objects from Scriptableobjects using Behavior Designer? (Say uf you're using SOs for data storage, stats etc?).

    Some use of Shared Variables?

    Also does Behavior Designer support EasySave2?
     
  49. opsive

    opsive

    Joined:
    Mar 15, 2010
    Posts:
    5,122
    You're able to save behavior trees to a scriptable object, is that what you're referring to?

    http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=51

    You can then get the variables using ExternalBehavior.GetVariable/SetVariable

    That's a good question - I haven't tested Easy Save with it. My gut says not without any integrations but it may surprise me :) I do have plans on adding saving and loading to the tree to a future version though.
     
  50. Duffer123

    Duffer123

    Joined:
    May 24, 2015
    Posts:
    1,215
    Although ive not purchased this asset yet, i was wondering if i created my rpg database within scriptableobjects could behavior designer access the values, variables and objects and same in lists within those scriptableobjects?