Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

MonoBehaviourTree - Simple event driven behaviour tree

Discussion in 'Assets and Asset Store' started by Qriva, Jul 18, 2022.

  1. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,092

    MonoBehaviourTree is open source behaviour tree solution for Unity projects, it provides core modules allowing to implement customized AI or decision making system. The tool includes a simple visual tree editor that makes making changes quick and easy.

    Asset store: https://assetstore.unity.com/packages/tools/ai/monobehaviourtree-213452
    Github repo: https://github.com/Qriva/MonoBehaviourTree

    Features:
    • Visual editor with draggable nodes and connections
    • Blackboard with local variables
    • Observable properties and fields with constant and reference mode
    • Fast and event driven behaviour tree
    • Node inspector
    • Customizable execution
    • Event driven conditional nodes and services
    • Built In 20+ basic nodes and 9 types of variables
    • Easy extendable code for custom nodes and variables
    • State (execution flow) visualization
    • Breakpoints

    Sidenote
    This project started because I couldn't find any free, decent behaviour tree asset meeting requirements of game I was working on. When I started working on it I was lacking experience to design it correctly, in result this tool is far from perfect because of many mistakes I made on my road.

    For this reason I would be eager to rewrite it, to make it more modular, with better blackboard, inspector, and many other things that went "wrong". However, first I would like to know if there are people who need this kind of asset, so in case you are interested in such a thing let me know in this thread!
    Also I am interested in any feedback, so go ahead and tell me what do you think.
     
    vexstorm and akuno like this.
  2. Corpvs

    Corpvs

    Joined:
    Nov 27, 2021
    Posts:
    2
    Hi, I've been testing with MonoBehaviourTree for a while
    He was very attractive to me because of his light weight and visualization,
    The Blackboard feature is also useful for many purposes.
    I am also trying some good ways to make AI, indeed some behavior tree plugins are too large.

    Modularity, is a good form, and I checked out some other AI resources. I found that not many have this modular plug-in idea.
    It is a fascinating thing to accumulate node written by yourself in each project.
    The stability and fault tolerance of MonoBehaviourTree would be better if it were higher.
     
  3. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,970
    That's pretty good. full debugging in the graph and good perfs despite using a blackboard!
    I decided against BT a long time ago but that;s temping!
    A utility selector would be very nice.
     
  4. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,092
    Thank you for the feedback! Can you explain a bit more what you mean by "utility selector"?
     
  5. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,970
    It's a node that evaluates the score of its children then choses the highest reward or randomly choses amongst the top 3. Score = how much it fulfills the needs of the character and can be negative, for example if the character stomach is full and needs fun and food source is far away (path length) then the feed branch will score negatively but if a TV is another character is close by then the socialize branch will have a high score.
     
  6. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,092
    Ah yes, actually I was in the half way to implement one, but then I realized it was implemented in the wrong way as node must persist state when aborted and finally I forgot to write it again. Still, I was not sure how exactly should be done - by weights or % and where should be inspector as connections are dynamic. I guess it would throw error when number of weights is different than number of connections.
     
  7. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,970
    Not sure what you're pondering.
    Scores would be per nodes, but you're saying that nodes don't keep state so you'd do that per link?
    In any case, the math that some people use is : multiply of all normalized score. I use add of non normalized score and this diverges fast, locking the AI in a loop of action, so i think those people are correct.
     
  8. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,092
    I mean, abort system requires nodes to behaviour in the same way in certain situations, otherwise the whole mechanism would not work - not big deal in any case. About the mentioned node, the idea is like this:

    upload_2022-10-12_9-40-38.png

    There are nodes with chance to be picked, however something have to hold this information, and this can't be children node - it has to be node C. There must be some array of weights or something (does not matter the form), and it's length should be the same as number of connected nodes. Again, not big deal, but when I started implementing this, there were missing features and it was a bit harder to make, and later as I said I just forgot. I am going to implement one soon.

    I want to rewrite MBT in the future, so if you got any other feedback you can throw it here.
    Thanks again
     
  9. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,970
    Right, children branches don't need to store anything for scoring but I think they need to contain the math to score themselves. C would then do the sum or mult of all these normalized scores.
    Something to consider also is that scoring takes trait into account so a creature with the lazy gene will downscore nodes that require long path.
    Why?
     
  10. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,092
    Well, as I said in the first post - poor design. Monos are not the best choice as nodes, blackboard variables work, but could be done way better + node editor itself has a lot of room to improve as it could be created with ui toolkit. Subtrees are kind of hacky too.
    On one side current design is simple, prototype friendly and also works quite well for not very complex trees, but I am pretty sure it would not scale well for something bigger.
     
  11. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,970
    the nice thing with monos is that you can plug scene stuff directly into them, personally i'm a big fan and that's how i do FSM that control game state. but i guess that's what blackboards are for
     
    Qriva likes this.
  12. Maria_Tonia

    Maria_Tonia

    Joined:
    Feb 28, 2019
    Posts:
    35
    Hi Qriva!
    Thanks a lot for your package, i just started to use it in my projects!! Installing via Package Manager and starting with Hello World is quite easy, i love it. And you have to my vote for a 2.0 Version :)

    These things come into my mind:
    - UtilitySelector as mentioned above would be great to allow smarter & more dynamic AI choices
    - optional Memory / last node pointer in sequences (not sure how to express it, i just read that some BT save the last position in a sequence so the next time it is continued it starts from there)
    - More Nodes :) Maybe also specific sensors like Eye-Sight, Hearing, Is-in-line-of-sight, etc. or behaviours like "flee", "flock", etc.
    - Use the new Unity UI Toolkit (i saw some videos on Youtube, e.g. TheKiwiCoder created a BT with new UI Toolkit)

    Regards, Maria
     
  13. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,092
    Thank you for the feedback!
    Could you explain a bit better this case? + what is the intended use case of this feature?
    Oh yes, this is reasonable request, however I am not sure how to handle this as lack of them is not just purely because of laziness :D. The thing is every project has different requirements and implemenation can vary between them. For example I could add nodes like MoveTo or Flee to control navmesh agent, but in my own project using agent is more complex and I would need my own. I am pretty sure many users could face the same problem. So what I think right now is to create separate repos containing some set of nodes and user can install them optionally. In any case I would still need list of such nodes, plus how they should work exactly.
    Yeah, I think started mine like 3 years ago and I guess UI toolkit was in early development so I haven't use it. I would like to rework it to graph view, but my time is limited and actually Unity still has both graph packages deprecated or something and they develop it internally... well, I can still use it, but I am very disappointed they failed to release official version.
     
  14. Maria_Tonia

    Maria_Tonia

    Joined:
    Feb 28, 2019
    Posts:
    35
    Hey! I think i should not request too many features, as i am a newbie and just started with Behaviour Trees (and also with MBT). I just read an article about Behaviour Trees with actions like flock, etc., parallel execution sequences, node memory. But i have no idea yet if i will need that or maybe is already covered by MBT. Still have to understand Services, Aborts, etc. Probably looking at the commercial BT's or the Unreal BT is better than asking me ;-)

    By the way, i asked ChatGPT to write a method for UtilitySelection & FlockingBehaviour. I still have to try the code if it works.And i will see if i need more Type References (Gameobjects, List of Gameobjects, Animator Components, etc.)

    Anyways, i would be happy if you keep developing this library (or refactor, if you think you can implement it better now)!
    Great work, also that it's documented & with examples is really nice! Thanks again a lot for your effort and that you share it with the community!
     
    Last edited: Jan 16, 2023
  15. Maria_Tonia

    Maria_Tonia

    Joined:
    Feb 28, 2019
    Posts:
    35
    FYI - this is what ChatGPT wrote for flocking (slightly adjusted for my project). It has to be adjusted & optimized in the future, but at least it works:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.AI;
    3. using MBT;
    4.  
    5. namespace My.AI.MBT
    6. {
    7.  
    8.     [AddComponentMenu("")]
    9.     [MBTNode("My/Flock", 500)]
    10.     public class Flocking : Leaf
    11.     {
    12.         public NavMeshAgent[] agents; // list of all navmeshagents that should be considered for flocking
    13.         public NavMeshAgent agent; // this agent that will be steered
    14.  
    15.         public float separationWeight = 1;
    16.         public float alignmentWeight = 1;
    17.         public float cohesionWeight = 1;
    18.         public float flockRadius = 50;
    19.         public float agentSpeed = 5;
    20.  
    21.         private void Start()
    22.         {
    23.             agents = FindObjectsOfType<NavMeshAgent>(); // temporarily for testing
    24.         }
    25.  
    26.         public override NodeResult Execute()
    27.         {
    28.             // Initialize the vectors
    29.             Vector3 separation = Vector3.zero;
    30.             Vector3 alignment = Vector3.zero;
    31.             Vector3 cohesion = Vector3.zero;
    32.  
    33.             var count = 0;
    34.             // Iterate through each agent
    35.             for (int i = 0; i < agents.Length; i++)
    36.             {
    37.                 // Ignore this agent if it is the current agent
    38.                 if (agents[i] == transform.gameObject) continue;
    39.  
    40.                 // Calculate the distance between the current agent and the other agent
    41.                 var distance = Vector3.Distance(transform.position, agents[i].transform.position);
    42.  
    43.                 // Check if the distance is less than the agent radius
    44.                 if (distance < flockRadius)
    45.                 {
    46.                     // Add the separation force
    47.                     separation += transform.position - agents[i].transform.position;
    48.                     // Add the alignment force
    49.                     alignment += agents[i].GetComponent<NavMeshAgent>().velocity;
    50.                     // Add the cohesion force
    51.                     cohesion += agents[i].transform.position;
    52.                     count++;
    53.                 }
    54.             }
    55.  
    56.             // Normalize the vectors
    57.             if (count > 0)
    58.             {
    59.                 separation = (separation / count) * separationWeight;
    60.                 alignment = (alignment / count) * alignmentWeight;
    61.                 cohesion = ((cohesion / count) - transform.position) * cohesionWeight;
    62.             }
    63.  
    64.             // Set the agent's velocity
    65.             agent.velocity = separation + alignment + cohesion;
    66.             agent.speed = agentSpeed;
    67.  
    68.             return NodeResult.success;
    69.         }
    70.     }
    71.  
    72. }
     
  16. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,092
    Code (csharp):
    1. if (agents[i] == transform.gameObject) continue;
    I don't think this line can work xD
    Well, I have seen it can produce neat things, but I guess its more useful as hint than direct code.
    For example assuming it was generated as whole this line is pretty dumb:
    agents[i].GetComponent<NavMeshAgent>().velocity;


    Anyway yeah, I will land probably several small fixes soon, but if you find some bugs or anything like that, feel free to create issue on github.
     
  17. Maria_Tonia

    Maria_Tonia

    Joined:
    Feb 28, 2019
    Posts:
    35
    Yeah, ChatGPT can maybe help a little but not always ;-)

    If you can write a good Flocking Node (or an example), you are very welcome :)
     
    Last edited: Jan 17, 2023
  18. Maria_Tonia

    Maria_Tonia

    Joined:
    Feb 28, 2019
    Posts:
    35
    I have two questions:

    1.) In your patrol example, Unity 2022.2.2f1 shows an error message in the inspector (i guess the array of patrol points?). Anyways, it works when i run it.

    upload_2023-1-17_22-46-29.png

    2.) I tried to create my own MBT with Random MoveToPoints (without defined patrol points), pursuing and attack behaviour. It seems to be working; in your example you used a Repeater. What is the benefit of that?

    upload_2023-1-17_22-51-20.png
     
  19. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,092
    Yes, this is one of things I want fix soon. For some reason it does not allow nested foldout header in inspector. It was not the problem in 2019.4, but I think this changed after they added reorderable list.

    There is no difference, it's there for demonstration purpose. Repeater just below the root should work the same as enabling repeatOnFinish. Usually Repeater is for when you want to "loop" only part of the tree.
     
    Maria_Tonia likes this.
  20. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,092
    Version 1.1.0 released - minor improvements
    • Added behaviour tree deltaTime and lastTick
    • Fixed Wait node time calculation (it was one frame ahead)
    • Fixed FoldoutHeader error in node inspector
    • Removed empty delegate from tick event
     
    Marti_Salazar, id0 and Maria_Tonia like this.
  21. Stroved

    Stroved

    Joined:
    Jan 3, 2014
    Posts:
    16
    Hey :) I've been using this for a few days now and I think it's really awesome and powerful, so thank you for sharing it (and for free!).

    I'm a bit confused by the SubTree node though. Would it be possible to create another sample with a SubTree to show how it works?

    Thanks again for the awesome package!
     
  22. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,092
    Good to hear it's useful to someone :)

    About subtree, I am very busy currently, so I am unable to create any additional examples. To be honest subtree is kind failure as it should be super easy and flexible and right now it does not meet those requirements. SubTree is just node to connect another child behaviour tree. The main problem is it must be connected from "both sides" - both in subtree node and that child MBT (parent property).
     
  23. unity_QJ7RazXzghZCzA

    unity_QJ7RazXzghZCzA

    Joined:
    Jul 9, 2021
    Posts:
    99
    +1
    Thanks for creating free, lightweight solution. I hope to see zoom and other features, or completely re-writed solution you mentioned before.

    Thanks for your work!
     
    gamecoding1999 likes this.
  24. gamecoding1999

    gamecoding1999

    Joined:
    May 8, 2019
    Posts:
    1
    I also hope there is a zoom function