Search Unity

[AI SCRIPTING] Panda BT: Behaviour Tree scripting

Discussion in 'Assets and Asset Store' started by ericbegue, Feb 26, 2016.

  1. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    @Nigey, I could reproduce the bug you've mentioned. It is indeed very annoying. The bug does occurs only with the current version (1.2.2) and does not occurred with the up coming version (1.2.3). I am suspecting it is related to the bug @BoredMormon discovered (see this post), this bug was making the BT being recompiled when an object is selected in the Hierarchy, and probably other undiscovered side effects. This will be fixed in the release of version 1.2.3.

    I would like to somehow quickly distribute the fix to you guys, so you don't have to wait for the fixed package being published on the Asset Store (the asset reviewing takes quiet some time). But I have to ensure first that I am not violating my agreements with Unity by doing so.
     
  2. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    That's exactly what I thought the issue was too. It seemed like it'd duplicate another version each time you moved the component. The delay got longer and longer each time you moved it. I've seen a few other assets on the asset store with the same issue of recompiling each time it's selected (A* Pathfinding, I'm looking at you).

    I didn't know about the asset reviewing phase. I suppose that does make sense. Well I've asked publishers for minor changes before via Email and they've sent it to me. So I'm guessing it's not a problem. In case you find it's okay to send the hotfix privately, my email is 'nigel_clark_@outlook.com'. Thanks for fixing it quick :).
     
  3. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Oh! The BT scripts not appearing on the prefab seems to be caused by the same bug. So, this is a 1-stone-3-birds-fix (maybe more, who knows). Anyway, everything will better in the 1.2.3 release.
     
    Nigey likes this.
  4. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Nice work. I'm personally happy with simply waiting out the review process. Should be quicker for updates?

    Either way none of this is time critical for me.
     
  5. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    I've got an answer from Unity, it's fine I distribute the new package directly. So if you don't want to wait for the Asset Store update, just PM me and I'll send the hotfixed package to you.
     
  6. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
  7. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    So far, I'm enjoying using Panda more than using the dialogue mini-language I wrote myself during the past week.

    Disclaimer: I hate Python. :) This is minor, but from time to time I stumble over PBT's indent-based hierarchy. Looking at the language you've created, I can't see a reason it's important. I agree it looks nice, but I don't understand why it must be enforced. I'm guessing it makes your parsing easier? Any chance this requirement could be dropped? Or am I missing some case where lack of indentation would introduce ambiguity? (My trees are still pretty simple at this point...)

    Another thought / suggestion / request...

    In using PBT for dialogue experiments, I found myself calling the same tasks over and over. To use the example you posted the other day, Say(text) would be an example of this. It is obvious those repeated calls belong in a separate class. I also separated the UI handling, so methods like Say() and Option() go into a generic Dialogue class that sits in between the dialogue script in the behavior tree and the UI.

    It quickly begins to feel wasteful to sprinkle copies of this Dialogue class on every single GameObject that needs to say something. Normally I would to implement it as a static class (there is almost no state-data and only one dialogue would ever be active at a given time) but this doesn't work because, by definition it isn't on the same GameObject, and of course, a static class can't be a MonoBehaviour.

    I'm sure you see where I'm going with this. I can define [Task] attributes on static methods but PBT can't find them. Is there some Unity-reason for this? As far as I know, .NET's GetCustomAttributes() should find [Task] anywhere in the project, right? As long as there are no naming ambiguities, would it be a problem to just call a named Task wherever it might be? I suppose this really only applies to static methods, but I tend to use them heavily for utility-style operations.
     
  8. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Yeah, I know what you mean about the Python indentation style. Sometimes I also have those "aargghhhh! ffffff..."-moments when somehow I end up with a mixed of spaces and tabs indentation in the same script rendering the hierarchy as ambiguous. I went for this style of indentation because it requires less typing than using brackets as in C/C++ or derived languages including C#. Also I believe is more readable, though it is sometime frustrating to have such a strict indentation. But, maybe I could support both styles... I don't know.

    For example this BT script:
    Code (CSharp):
    1. tree "DeliverPreciousObject"
    2.     fallback
    3.         while not IsThereThreatOnTheWay
    4.             sequence
    5.                 MoveTo_PreciousObjectLocation
    6.                 PickUp_Object
    7.                 MoveTo_PreciousObjectDeliveryLocation
    8.         tree "SecurePreciousObject"
    9.  
    Would become in a bracket style indentation:
    Code (CSharp):
    1. tree "DeliverPreciousObject"
    2. {
    3.     fallback
    4.     {
    5.         while{ not{IsThereThreatOnTheWay} }
    6.         {
    7.             sequence
    8.             {
    9.                 MoveTo_PreciousObjectLocation
    10.                 PickUp_Object
    11.                 MoveTo_PreciousObjectDeliveryLocation
    12.             }
    13.         }
    14.         tree "SecurePreciousObject"
    15.     }
    16. }
    Somehow, I prefer the python style. But maybe it's just a matter of taste. I would like to have more feedback on this. Or maybe there is another way to specify hierarchies (Disclaimer: I am definitely not going towards an xml style, don't even suggest it, it would be a plain and definitive "No!!!")?

    I've made a small project trying to implement this Panda BT dialog system. And so far I'm pretty satisfied of the result. I have the intention to place this solution on the Asset Store as a Panda BT extension. But since you are the catalyst of this idea, I will send the project to you in PM. Basically, any character in you game that speaks, therefore could trigger a dialogue has to have a specific MonoBehaviour attached to it ( there's no other way around this). However, that does not mean that this MonoBehaviour has to handle all the UI, this could be delegated to a unique object in the scene. So the "Say" task can have a "static smell".

    In fact, my first Panda implementations did not require the [Task] attribute. But I thought maybe it's a good idea to have a way to specify that you have the intention to use a method from a BT script, this would avoid some ambiguous situations where a method with the same name is already defined but has nothing to do with a BT script. That's why there is this [Task] attribute: you know that this method is to be used from a BT script.

    Also, it is simple and straight forward that the task implementations should be implemented on the same GameObject the PandaBehaviour component is attached to. This also introduces some flexibility. For instance, you can have the same BT script attached to different GameObjects but with different different task implementations. Such that you have the same high level logic but different effective implementation, it is a mechanism somewhat similar to polymorphism in OOP.

    I agree it is technically possible to not have the restriction of having the task implementation attached to a specific game object. But you would need to introduce some task implementation searching or priority, which would introduce more complications. I would like to keep Panda BT as simple and straight forward as possible. But I am not closed to suggestions and ideas that would come in handy in practice. Like having a way to specify a global-default-tasks. But again that would introduce extra configurations. Which are not necessary, since it so easy to create a new MonoBehaviours and attached to GameObjects.

    Panda BT is a really young project and there is always place for improvements. I'm really glad to have such constructive critics and suggestions. Please keep them coming up!
     
    Last edited: Apr 3, 2016
  9. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    Thanks, I'd be interested in checking out what you came up with.

    In terms of Tasks which aren't associated with a GameObject, I wasn't hoping for anything complicated. If there is ambiguity, I'd be ok with it just throwing an error. With Unity serializing and deserializing things all over the place, no constructors on MonoBehaviours, etc, I'm just not a big fan of composing game elements and relationships through the editor, I prefer a more data- and code-driven approach.
     
  10. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    After considerations and weightings, having an in-inspector BT editor would make the workflow much simpler and more streamlined than editing the BT script with an external text editor (though I will keep this as an option). An in-inspector editor would eliminate all the indention hassles (;) @MV10 ) and it could open the option to have auto-completion and error checking directly within the Inspector.

    The Unity scene Hierarchy tab could be a good model to start with, it's rather easy to organize a hierarchy using it (obviously). So I am going toward this approach to organize the node hierarchy of a behaviour tree.

    @tatoforever I think this new feature would match pretty well what you are suggesting. (?)

    Thought, this is not going to be implemented soon. I need to give it more thoughts. Also, I need to refactor the PandaBehaviour inspector a lot, since it was originality not build to be an editor.

    This in-inspector editor is a good reason to increment the minor version number, so this is going to be a feature of Panda BT version 1.3.x!

    Stay tuned!
     
    Last edited: Apr 5, 2016
    tatoforever likes this.
  11. tatoforever

    tatoforever

    Joined:
    Apr 16, 2009
    Posts:
    4,368
    @ericbegue,
    When I suggested such editor I was thinking in something like this:

    Would probably be better in a separated Editor (independently) so you can keep the actual Inspector + text-script as an option and a separate editor with the cut/paste/copy/drag/drop functionalities that load/saves the same text asset file your current Inspector does.
    Regards,
     
  12. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    One minor note on your documentation -- you don't explain using "tree" to jump to processing a tree node (versus a top-level use of the tree keyword to define the start of a tree).

    Now that I have a sort of basic framework built around this, I'm trying to do more complex dialogues. Generally speaking dialogue trees are either of the "waterfall" style -- it progresses forwards and you never really go back; or they're of the "hub" style where the player has a menu of subjects they can pursue, but you return to the hub later.

    The tree circular reference restriction means the hub style is effectively impossible to implement. Though I'll congratulate you for trapping multi-level circular reference; I tried to trick the thing by adding something like this:

    Code (csharp):
    1. tree "Shopping"
    2.     xxxxxxxxxxxxx
    3.  
    4. tree "RestartShopping"
    5.     tree "Shopping"
    I understand why you block this -- calling a tree is really awaiting the final output of processing that tree, whereas I'm abusing it to implement branching and jumping.

    I'd definitely like to take a look at the dialogue system you've built, and I'm happy to share the mutant hack job I've cobbled together for my own testing (as well as the dialogue-specific mini-language I also whipped up the other day).

    (Oh and by now I at least see where indent/structure is necessary... I still don't like it, but back at the start I thought it also wasn't needed.)
     
  13. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    I'll try to make the tree node more clear in the docs. But I'm also thinking about modifying the language such that a tree could be called exactly as a task and the tree name won't be a string, for instance:

    Something like this:
    Code (CSharp):
    1. tree "Root"
    2.     fallback
    3.         tree "ChasePlayer"
    4.         tree "AvoidPlayer"
    5.         tree "Idle"
    6.  
    7. tree "ChasePlayer"
    8.     while IsIt
    9.         // ...
    10.  
    11. tree "AvoidPlayer"
    12.     while not IsIt
    13.         // ...
    14.  
    15. tree "Idle"
    16.     while
    17.         // ...
    18.  
    Would become:
    Code (CSharp):
    1. tree Root
    2.     fallback
    3.         ChasePlayer
    4.         AvoidPlayer
    5.         Idle
    6.  
    7.  
    8. tree ChasePlayer
    9.     while IsIt
    10.         // ...
    11.  
    12.  
    13. tree AvoidPlayer
    14.     while not IsIt
    15.         // ...
    16.  
    17. tree Idle
    18.     while
    19.         // ...
    20.  
    Now, obviously it's confusing what is a task and what is a sub-tree but I could easily color them in different colors in the Inspector.
    Let me know what do you guys think about this? or do you have some suggestions to make the language clearer and more practical?

    @MV10
    A circular definition of a Tree is indeed not allowed, simply because the returned status of the tree will be undefined.
    Though, I think the "hub" style dialogue is possible using some fallback and repeat nodes to implement your jumping/branching. I've PM you a small project I'm working on.

    The indentation specify the child/parent relation of the the nodes therefore defining a tree, that's it. What do you not like about it? How would you specify an hierarchy instead?
     
    Last edited: Apr 6, 2016
  14. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    I actually kind of wondered about having to put tree names in quotes since the only other place quotes are needed are string parameters to tasks. I think that second syntax would make it more confusing. I think what would be more clear is "tree" to define a sub-tree, and another keyword to process it (maybe "exec" for example).

    For my needs, I would like to see something that simply ended processing of the current tree and picked it up on another tree -- a "jump" command, perhaps. If you needed to put it into your succeed/fail framework, maybe jump always succeeds but it also unwinds the stack so you don't have this circular-reference/recursion problem. Obviously I haven't seen the guts of the code, I'm just throwing it out there from the user side.

    All I was saying about indentation is that now I see cases where that structure matters. In my earliest, very simple tests, I wasn't building anything deep enough or with enough steps that it mattered. Mostly I object to whitespace, anything else would satisfy me. Heck, dashes. A dialogue tree in a real game is often going to run very deep. Not that I want to dominate your concerns with dialogues but it just happens to be my focus right now.
     
  15. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Panda BT free 1.2.3 has finally reached the Asset Store.

    Here is the release notes:

    Core
    • Optimized for GC Allocations per frame (after initialization, 0B is allocated by the engine).
    • Added Task.isInspected, which returns whether the current BT script is displayed in the Inspector.
      (Use to avoid GC allocation when formatting string for debugInfo)
    • Added PandaBehaviour.Compile( string source ) and PandaBehaviour.Compile( string[] sources ),
      which are used to make BTs from strings instead of TextAssets.
    • Added built-in task DebugBreak, which breaks (pauses the editor) and succeeds immediately.
    Fixes:
    • Fixed BT being reset when object is selected in the Hierarchy.
    • Built-in task WaitAnyKeyDown had parameter, now removed.
    Minor changes:
    • Simplified management of BT update and recompilation when scripts has been modified.
     
    MV10 likes this.
  16. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    This is nice. I'm guessing it gives back a PandaBehaviour that can be Reset and started by setting the tick mode to Update or whatever is needed? Does Task resolution happen within the GameObject context of the script that is compiling it? For my dialogue needs this sounds like the way to make a dynamic store feature... (Not that my game will have store fuctionality, but it makes for a great test case of more complex interactions!)
     
  17. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    That's also my though about putting the tree names in quotes, it somehow highlights it and differentiates from regular task.

    Do you mean something like:
    Code (CSharp):
    1. tree "Root"
    2.     fallback
    3.         subtree "ChasePlayer"
    4.         subtree "AvoidPlayer"
    5.         subtree "Idle"
    6. tree "ChasePlayer"
    7.     while IsIt
    8.         // ...
    9. tree "AvoidPlayer"
    10.     while not IsIt
    11.         // ...
    12. tree "Idle"
    13.     while
    14.         // ...
    (?)

    If you want to interrupt a tree and jump to another tree, you could use a fallback combine with a while node.
    Code (CSharp):
    1. tree "Root"
    2.     fallback
    3.         while isSomeConditionTrue
    4.             tree "WhenTheConditionIsTrue"
    5.         tree "WhenTheConditionIsFalse"
    6.  
    7. tree "WhenTheConditionIsTrue"
    8.     // do some stuffs
    9.  
    10. tree "WhenTheConditionIsFalse"
    11.     // do some other stuffs
    If that example does not do what you want, could you give more concrete example of what you want to implement?

    The BT script with dashes would look like:
    Code (CSharp):
    1. tree "PlayTag"
    2. -fallback
    3. --tree "ChasePlayer"
    4. --tree "AvoidPlayer"
    5. --tree "Idle"
    6.  
    7. // Move to the player while we are 'it'.
    8. tree "ChasePlayer"
    9. -while IsIt
    10. --sequence
    11. ---SetDestination_Player
    12. ---MoveToDestination
    13. ---Wait 1.0
    14.  
    15. // Avoid the player while we are not 'it'.
    16. tree "AvoidPlayer"
    17. -while not IsIt
    18. --sequence
    19. ---IsPlayerNear
    20. ---SetDestination_Random
    21. ---IsDirectionSafe
    22. ---MoveToDestination
    23.  
    24. // Idle when we are not 'it' and the player is far.
    25. tree "Idle"
    26. -while
    27. --sequence
    28. ---not IsIt
    29. ---not IsPlayerNear
    30. --repeat Succeed // Repeat doing nothing.
    I actually like this idea, you can directly see the depth for particular node just by counting the dashes. That's good alternative to spaces and tabulations.
    or maybe with dots:
    Code (CSharp):
    1. // Move to the player while we are 'it'.
    2. tree "ChasePlayer"
    3. .while IsIt
    4. ..sequence
    5. ...SetDestination_Player
    6. ...MoveToDestination
    7. ...Wait 1.0
    hhmmm... I somehow prefer the dashes version. The big problem with that is most editor works already well with the tab key. For instance, it would not be possible to indent a block of code using the dashes as indentation. BTW, I would suggest to use an advanced text editor such as Notepad++, with which you can actually display the tabulations (and make a similar visual as with the dashes), I used that regularly.

    Also, when your tree starts to grow very deep, you can group the deepest nodes into subtrees, which would make the reading/editing easier.
     
  18. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    Good point about grouping into subtrees. And you're right, I use VStudio for everything and it couldn't cope with the dashes, even though I like that look too.

    Your tree / subtree keyword is what I had in mind, yes.

    Your fallback / while to jump to another subtree doesn't resolve the circular reference which is really what I had in mind. If there was a way to say, "Hey, I'm done processing this whole tree I'm in, ditch the results and jump to this other tree and start over," that's what I was after. It seems to me in that case a circular reference shouldn't matter (the obvious case is a subtree for dialogue-based shopping -- the player would expect to return to the start of the shopping tree after they make a purchase -- it was your original dialogue example which made me realize this).
     
  19. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    I think it's possible to implement this. Let's say, using the shopping example, that the vendor proposed a its list of items until the player is done with buying stuffs.
    That can be implemented with the following BT Script by introducing IsContinuingShopping which indicates whether the player which to continue shopping or not:

    Code (CSharp):
    1. tree "Root"
    2.  
    3.     Say "Welcome! Do you want to buy something?"
    4.     SetContinueShopping true
    5.     fallback
    6.         repeat // Repeat shopping until the player answers "No".
    7.             sequence
    8.  
    9.                 Option 0 "Yes"
    10.                 Option 1 "No"
    11.          
    12.                 WaitPlayerChoice
    13.  
    14.                 fallback
    15.                     sequence Choice 0
    16.                         Say "Here is what I have:"
    17.                         SetContinueShopping true
    18.                         tree "Shop"
    19.                     sequence Choice 1
    20.                         Say "Alright, please come back later."
    21.                         SetContinueShopping false
    22.          
    23.                 IsContinuingShopping // We quit repeat shopping when that turn to false.
    24.                 Say "Do you want to buy something else?"
    25.          
    26.     Say "Good bye!"
    27.  
    28.  
    29. tree "Shop"
    30.     // Display a list of item to buy
    Is that close to what you want to do?
     
    Last edited: Jun 5, 2016
  20. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    PandaBehaviour.Compile(*) is called on a PandaBehaviour component already attached to a GameObject. So, the tick configuration and the tasks resolution are the same as using regular TextAssets.
    This feature open the possibility to dynamically generate behaviour at run time, which can be pretty powerful if you build yourself a solid framework (thinking about some template engine). Though, you can already do a lot of stuffs by combining different TextAssets on a the same PandaBehaviour, note that it can receives more than one TextAsset and so that the final BT is a combination of them.
     
    tatoforever and MV10 like this.
  21. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    Ah ok, that's cool. I can see a lot of uses for that. Just the other night I was thinking it would be nice to generate new rules on the fly, I didn't expect to get it today!
     
  22. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,362
    I wonder if adding an "overload" to .debugInfo that takes StringBuilder would solve that.

    Code (CSharp):
    1. StringBuilder datString = new StringBuilder();
    2. // in the task
    3. if( Task.isInspected )
    4.     Task.current.debugInfoNoAlloc = datString.AppendFormat("t-{0:0.000}",  tta);
     
    Last edited: Apr 7, 2016
  23. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    @laurentlavigne Thank you for the suggestion. But StringBuilder is efficient at concatenating strings, not at formatting string. I've made a small test, and there are peaks of allocated memories.

    I guess what we need would be a function that format a on a pre-allocated string buffer, but that seems to not exist in C#. The problem with Format (or AppendFormat) is that it will generate a string, therefore allocating memory. So we just need to avoid Format if we want to optimize for GC, and using Task.isInspected seems to be the way to go. There is also the possibility to define a callback for the debug info. Something like:

    Code (CSharp):
    1. Task.current.debugInfoCallback = () => string.Format("t-{0:0.000}",  tta);
    Then the engine would call this callback only when necessary, but it seems less straight forward. What do you guys think about this?

    @laurentlavigne In your Asset Store review (btw, thanks, it helps a lot) you've mentioned that you would like to see a similar tool as Panda BT but for GOAP (Goal Oriented Action Planning). I am not familiar with this technique. Could provide some situations and examples where GOAP would useful. And maybe what would GOAP script look like in Panda style.
     
    Last edited: Apr 8, 2016
  24. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,362
    GOAP is fantastic when you have SIM like AI where tasks interact in complex ways to fulfill goals. As you add tasks and actions you don't have to update the graph like you would in BT, it does it for you. In fact adding actions become an "unlock skill" type thing and you end up with creative AI that surprise you.

    Imagine you have a sith lord agent 007 with the goal (and the license) to kill you, but also to survive. Given Bond Vader the following actions and item in inventory:
    actions: kill by stabbing, kill by sniping, machinegun straffing, casting fireball spell, use the force to break off a ceiling beam on your head, eat, go zen
    inventory: dagger, happy pill, energy = 20, zen = 6
    kill by stabbing requires a dagger (check) but due to being close combat has a computed cost of 20
    casting fireball spell requires energy >= 50 and zen >= 20 and can be done remotely which brings the cost to 2
    granola bar contain energy = 30 and happy pill contain zen = 14
    eating has a cost of 0.5
    there is a granola bar a meter away, which brings the cost of walking to that granola to 1.
    The AI courses the graph of actions and preconditions and finds the best which is off course:
    "walk to granola bar and eating it regain energy, pop a happy pill to gain zen THEN cast a fireball spell on your face"

    An example in Panda, using this unity GOAP project as basis http://gamedevelopment.tutsplus.com...d-action-planning-for-a-smarter-ai--cms-20793.
    the dropoff tool action is something like this:

    Code (CSharp):
    1. action "dropOffTool"
    2.     preconditions
    3.         "has new tools" true
    4.     effects
    5.         cost 1
    6.         "has new tools" false
    7.         "collect tools" true
    8.     reset
    9.         "dropped off tools" false
    10.         "target supply pile" null
    11.         "timer" 0
    12.     isDone
    13.         return "dropped off tools"
    14.     requiresInRange
    15.         return true
    16.     checkProceduralPrecondition
    17.         // some language find closest supply pile, maybe BT?
    18.         // assign target
    19.         cost += distanceToTarget*0.01
    20.         // return true if target exists
    21.     perform
    22.         // fsm or bt
    23.         goto "target supply pile"
    24.         wait duration  
    25.         "target supply pile".numTools += 2
    26.         "dropped off tools" true
    The idea is there are sections which always get called when solving the graph : preconditions, effect, reset etc....
    Inside each section is a BT, since I still don't know how to write a foreach loop or "if" in BT I commented out the checkProceduralPrecondition section, same for return and .numTools, I made ugly soup, feel free to correct.
    One file per action and one file per goal. An agent can have many goals and actions which could conflict but that's what cost and priority are for. Note that cost can be programmatically set in checkProceduralPrecondition

    Code (CSharp):
    1. goal "collect tools"
    2.     priority 4
    3.     "collect tools" true
    or could have set priority programmatically such as
    Code (CSharp):
    1. goal "survive"
    2.     priority
    3.         being.isHealthy ? 1000 : 0
    4.     "eat" true
    5.  
    Which will keep that goal to the bottom of the pile as long as the being is healthy

    Thanks for the info regarding stringbuilder format, I was assuming™.
    Debug is only called once a frame with inspector open so it's no big deal anyway.
     
    Last edited: Apr 8, 2016
    tatoforever likes this.
  25. Lionel_Leeser

    Lionel_Leeser

    Joined:
    Jan 29, 2015
    Posts:
    2
    Hi Eric,

    I was getting mad with some strange FSM implementation for my AIs. And I found your asset !

    Waouw, you have done great job ! that's a very nice asset ! I love it.

    I have one question for you !

    What bring the pro version exactly ?

    because it seems that the free version could be enought for my needs but can I use it for commercial games ?


    Thanks.

    Lionel Leeser
     
  26. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    @laurentlavigne
    Thank you for your explanation of GOAP. So with this technique, you define some objectives and their requirements, then the AI will take the best path of actions (by taking into account some cost evaluations) to accomplish the goals. This sounds interesting. But I am wondering whether this technique can be integrated with BT or whether it will conflict with it. It is definitely a technique to give some considerations. Any input on that subject is welcome.
     
    Last edited: Apr 9, 2016
  27. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Hi @Lionel_Leeser

    I'm glad Panda BT is helping that well to implement your AIs. (I know how frustrating it is to work with FSM).

    It's great that you like it! Please post a review on the Asset Store, it helps a lot, I'll appreciate.

    With the pro version, you have break point debugging directly in the inspector. You can setup a different types of break point (when a task starts, fails or succeeds) in your BT script, which is useful for debugging.

    The pro version contains the sources also.

    Also, I'm currently developing an in-Inspector editor, which would be a pro feature as well.

    You can use Panda BT for commercial games without problems.

    However, besides of giving you a better karma, buying the pro version will come has a great support for me to further develop and maintain this tool.
     
    Last edited: Apr 9, 2016
    tatoforever likes this.
  28. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,362
    BT can be used to define each section of an action.
    Think of it as adding a planning layer on top of what you already implemented.
     
    Last edited: Apr 10, 2016
  29. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    @laurentlavigne
    Let see if I can explain where I see a conflict.

    Both GOAP and BT are planners. GOAP is a preemptive planner, it answers the question:
    "Given the current state of the world, what is the best path of actions to reach my goal?"
    Whereas BT is a reactive planner, it answers the question:
    "Given the current state of the world, what is the best action I can do now?"

    It seem they solve the same problem but in different way.

    Now, I am wondering whether both systems can be mixed and how they would complement each other. Or maybe it's best to keep both systems separated and apply them appropriately. I like to keep things simple: I'd prefer to make a tool that does only a few thing and do it well, rather that a tool that makes a lot of things in a confusing way. At the end, would it be better to have two packages: Panda BT and Panda GOAT, or have a single package Panda AI that implements both system.
     
    Last edited: Apr 10, 2016
  30. ZJP

    ZJP

    Joined:
    Jan 22, 2010
    Posts:
    2,649
    Vote for two packages. :)
     
  31. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,362
    @ericbegue I don't see a conflict, more a sub set super set type thing, in other word, goap or htn or weighted decision tree are layers on top of BT to simplify AI design and make it more expressive.

    BT already does actions and the logic that would drive precondition. Add a few extra keywords to do cost evaluation, action pathing and the goap/whatever scaffolding - meaning the block definition like action, result, precondition, init - and you have decision layers that make designing your AI easier.
    In other word extend the BT language to allow more high level stuff and turn this into a framework for other ai flavors.

    The benefit is one UI, one API that can scale in expressiveness and performance to fit the project. Want Banished? Add action pathing and toggle the actions to match the character's assignment, want The Sims? Weight each action with what the character feels like doing at the moment. Want a zombie crowd? A few lines of BT is enough. Want something that seems to learns? randomly chose actions or goals and store the result to weight up or down that action.
    Second benefit is any system can be baked into pure bt, removing all expensive action pathing.

    At least worth a deeper look so here are a few links.
    bird's eye view of AI and make you hungry:
    http://intrinsicalgorithm.com/IAonAI/tag/behavior-tree/

    An elegant frameworks is better than sticking to one AI flavor
    http://aigamedev.com/open/editorial/2010-retrospective/
    http://aigamedev.com/open/editorial/2013-retrospective/

    HTN ftw:
    http://aigamedev.com/open/coverage/htn-planning-discussion/

    And if you realy like equations this is for you.
    https://users.ics.aalto.fi/rintanen/planning.html
    http://web.stanford.edu/group/nasslli/courses/boutilier/Lecture1.pdf
    http://aima.cs.berkeley.edu/2nd-ed/newchap11.pdf
     
    Last edited: Apr 11, 2016
  32. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    @laurentlavigne
    Integrating GOAT with BT seems to be good idea. It seems GOAT is a more abstract model than BT. Defining some BT tasks, then defining some GOAT action graph and and some cost functions, and let the AI decide what is the best thing to do... that sounds really flexible and attractive.

    Now, what is more my concern is to define that GOAT layer that would integrate well with BT: how to define the actions, the pre-conditions, the costs, the actions dependencies, it a simple and clear way. I would need some time to learn more about GOAT and digest all these.

    Thank you for the links!
     
  33. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
  34. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    @MV10
    Thank you for this link, it contains really interesting articles!
    So far, I also think GOAP it's very different from BT, that's why I am not completely convinced it can be a mixed easily. Though, it seems an interesting technique worth to learn more about.
     
    tatoforever likes this.
  35. Deleted User

    Deleted User

    Guest

    I would be very excited about some kind of planning-based AI. I don't think the techniques could necessarily be mixed, because in all my research I've never seen any game that uses both at the same time.

    A few relevant GOAP links:
    * http://gamedevelopment.tutsplus.com...d-action-planning-for-a-smarter-ai--cms-20793
    * https://github.com/sploreg/goap
    * http://alumni.media.mit.edu/~jorkin/goap.html

    Related to that is HTN (hierarchical task network, a version of Simple Hierarchical Ordered Planning):
    * https://sourceforge.net/projects/chpplanner/
    * http://pjvgastel-programming.blogspot.ca/2013/10/cuhp-simple-c-task-planner-for-unity3d.html
    * http://pjvgastel-programming.blogspot.ca/2014/06/improving-performance-of-my-unity3d-htn.html
    * http://aigamedev.com/open/coverage/htn-planning-discussion/

    There was actually an HTN project for Unity but it was discontinued. It's a damn shame. Maybe someone could resurrect it?
    * http://stagpoint.com/planner/
    * https://www.assetstore.unity3d.com/en/#!/content/26747
     
  36. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    @ashking Thank you for the links.

    And thank you guys for all the ressources about GOAP and HTN. These are really interesting articles. But I think I have enough ressources to read now :). I will definitely give it some thoughts to these techniques and see if I can make something out of it.
     
  37. andyblem

    andyblem

    Joined:
    Nov 11, 2014
    Posts:
    26
    You can add a drag and drop design just like in Behavior Designer to help visualize the behavior tree. You can also put a comparison between the free version and the pro version.I really like the concept behind your asset It is one the best tools around
     
    Last edited: May 4, 2016
  38. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    @andyblem The drag and drop editor is a work in progress. Right now, I'm in the polishing phase, so it is nearly ready to be wrapped up and submitted for review. So, stay tuned! This editor will be a pro feature. I will put a table in the documentation to sum up the differences between the pro and the free edition. Currently the pro edition comes with break points debugging and the sources.

    Great that you like this asset! Thank you for saying it is one of the best tools around. I'd really appreciate if you leave a review on the assets store. It really helps to increase the visibility of this tool, which comes as a great support.
     
  39. andyblem

    andyblem

    Joined:
    Nov 11, 2014
    Posts:
    26
    I have downloaded a free version of your Asset. Created a new project, import it, open a scene and tried to build it for windows phone 8.1 and it gives me fourteen errors. The other builds were successfull(Standlone, Android and HTML5). So you have something to work on again. I will raise money to buy the full version because I have faith that this thing can reach greater heights. I am also developing a game for my University dissertation and I will be using your asset to implement my A.I. You can check my work on this youtube channel.
     
    Last edited: May 5, 2016
  40. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    @andyblem Sorry that there are errors in for windows phone. Thank you for reporting them. So far, I have no experience with this platform, but I will have a closer look at it and try to fix those errors. I did a quick check with my current installation (Unity 5.2.1f1), which build for windows phone 8.0. There was no errors during the building of the project from unity and from VS. However, I could not deploy the app to the emulator (I have no windows phone device, but I think the emulator should be a good testing platform), but I guess it has more to do with my inexperience with this platform. I will try again this weekend but with a 8.1 setting. For my information, could you post the errors you have obtained?
     
  41. andyblem

    andyblem

    Joined:
    Nov 11, 2014
    Posts:
    26
    Here is the list of errors
    Code (CSharp):
    1. Reference Rewriter found some errors while running with command --target="Temp\StagingArea\PandaBehaviour.dll" --additionalreferences="Temp\StagingArea" --platform="C:\Program Files (x86)\Windows Phone Kits\8.1\References\CommonConfiguration\Neutral\Windows.winmd" --support="Temp\StagingArea\WinRTLegacy.dll" --supportpartialns=Unity.Partial --system=System --dbg=pdb --framework="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\WindowsPhoneApp\v8.1" --alt=System.Xml.Serialization --ignore=System.IConvertible,mscorlib.
    2. Error: method `System.Delegate System.Delegate::CreateDelegate(System.Type,System.Object,System.Reflection.MethodInfo)` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Boolean Panda.BTTask::Bind(System.Object).
    3. Error: method `System.Delegate System.Delegate::CreateDelegate(System.Type,System.Object,System.Reflection.MethodInfo)` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Boolean Panda.BTTask::Bind(System.Object).
    4. Error: type `System.Reflection.Binder` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Reflection.MemberInfo Panda.BTTask::GetTaskMember(System.Object).
    5. Error: type `System.Reflection.ParameterModifier` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Reflection.MemberInfo Panda.BTTask::GetTaskMember(System.Object).
    6. Error: method `System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type[],System.Reflection.ParameterModifier[])` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Reflection.MemberInfo Panda.BTTask::GetTaskMember(System.Object).
    7. Error: method `System.Reflection.FieldInfo System.Type::GetField(System.String,System.Reflection.BindingFlags)` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Reflection.MemberInfo Panda.BTTask::GetTaskMember(System.Object).
    8. Error: method `System.Reflection.PropertyInfo System.Type::GetProperty(System.String,System.Reflection.BindingFlags)` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Reflection.MemberInfo Panda.BTTask::GetTaskMember(System.Object).
    9. Error: type `System.Security.Cryptography.SHA256Managed` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[] Panda.BTLAssetManager::GetHash(System.String).
    10. Error: type `System.Security.Cryptography.SHA256Managed` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[] Panda.BTLAssetManager::GetHash(System.String).
    11. Error: method `System.Void System.Security.Cryptography.SHA256Managed::.ctor()` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[] Panda.BTLAssetManager::GetHash(System.String).
    12. Error: type `System.Security.Cryptography.SHA256Managed` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[][] Panda.BTLAssetManager::GetHashes(UnityEngine.TextAsset[]).
    13. Error: type `System.Security.Cryptography.SHA256Managed` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[][] Panda.BTLAssetManager::GetHashes(UnityEngine.TextAsset[]).
    14. Error: method `System.Void System.Security.Cryptography.SHA256Managed::.ctor()` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[][] Panda.BTLAssetManager::GetHashes(UnityEngine.TextAsset[]).
    15.  
    16. UnityEngine.Debug:LogError(Object)
    17. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:579)
    18. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    19. UnityEditor.HostView:OnGUI()
    20.  
    21. Reference rewriter: Error: method `System.Delegate System.Delegate::CreateDelegate(System.Type,System.Object,System.Reflection.MethodInfo)` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Boolean Panda.BTTask::Bind(System.Object).
    22. UnityEngine.Debug:LogError(Object)
    23. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    24. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    25. UnityEditor.HostView:OnGUI()
    26.  
    27. Reference rewriter: Error: method `System.Delegate System.Delegate::CreateDelegate(System.Type,System.Object,System.Reflection.MethodInfo)` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Boolean Panda.BTTask::Bind(System.Object).
    28. UnityEngine.Debug:LogError(Object)
    29. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    30. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    31. UnityEditor.HostView:OnGUI()
    32. Reference rewriter: Error: type `System.Reflection.Binder` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Reflection.MemberInfo Panda.BTTask::GetTaskMember(System.Object).
    33. UnityEngine.Debug:LogError(Object)
    34.  
    35. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    36. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    37. UnityEditor.HostView:OnGUI()
    38.  
    39. Reference rewriter: Error: type `System.Reflection.ParameterModifier` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Reflection.MemberInfo Panda.BTTask::GetTaskMember(System.Object).
    40. UnityEngine.Debug:LogError(Object)
    41. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    42. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    43. UnityEditor.HostView:OnGUI()
    44.  
    45. Reference rewriter: Error: method `System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type[],System.Reflection.ParameterModifier[])` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Reflection.MemberInfo Panda.BTTask::GetTaskMember(System.Object).
    46. UnityEngine.Debug:LogError(Object)
    47. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    48. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    49. UnityEditor.HostView:OnGUI()
    50.  
    51. Reference rewriter: Error: method `System.Reflection.FieldInfo System.Type::GetField(System.String,System.Reflection.BindingFlags)` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Reflection.MemberInfo Panda.BTTask::GetTaskMember(System.Object).
    52. UnityEngine.Debug:LogError(Object)
    53. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    54. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    55. UnityEditor.HostView:OnGUI()
    56.  
    57. Reference rewriter: Error: method `System.Reflection.PropertyInfo System.Type::GetProperty(System.String,System.Reflection.BindingFlags)` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Reflection.MemberInfo Panda.BTTask::GetTaskMember(System.Object).
    58. UnityEngine.Debug:LogError(Object)
    59. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    60. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    61. UnityEditor.HostView:OnGUI()
    62.  
    63. Reference rewriter: Error: type `System.Security.Cryptography.SHA256Managed` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[] Panda.BTLAssetManager::GetHash(System.String).
    64. UnityEngine.Debug:LogError(Object)
    65. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    66. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    67. UnityEditor.HostView:OnGUI()
    68.  
    69. Reference rewriter: Error: type `System.Security.Cryptography.SHA256Managed` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[] Panda.BTLAssetManager::GetHash(System.String).
    70. UnityEngine.Debug:LogError(Object)
    71. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    72. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    73. UnityEditor.HostView:OnGUI()
    74.  
    75. Reference rewriter: Error: method `System.Void System.Security.Cryptography.SHA256Managed::.ctor()` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[] Panda.BTLAssetManager::GetHash(System.String).
    76. UnityEngine.Debug:LogError(Object)
    77. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    78. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    79. UnityEditor.HostView:OnGUI()
    80.  
    81. Reference rewriter: Error: type `System.Security.Cryptography.SHA256Managed` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[][] Panda.BTLAssetManager::GetHashes(UnityEngine.TextAsset[]).
    82. UnityEngine.Debug:LogError(Object)
    83. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    84. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    85. UnityEditor.HostView:OnGUI()
    86.  
    87. Reference rewriter: Error: type `System.Security.Cryptography.SHA256Managed` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[][] Panda.BTLAssetManager::GetHashes(UnityEngine.TextAsset[]).
    88. UnityEngine.Debug:LogError(Object)
    89. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    90. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    91. UnityEditor.HostView:OnGUI()
    92.  
    93. Reference rewriter: Error: method `System.Void System.Security.Cryptography.SHA256Managed::.ctor()` doesn't exist in target framework. It is referenced from PandaBehaviour.dll at System.Byte[][] Panda.BTLAssetManager::GetHashes(UnityEngine.TextAsset[]).
    94. UnityEngine.Debug:LogError(Object)
    95. PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:581)
    96. PostProcessWinRT:process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:123)
    97. UnityEditor.HostView:OnGUI()
    From the errors above I can deduce that some of the methods you used are not available on the windows phone 8.1 platform. So you basically have to find a different way of doing the same thing but that is supported in windows phone 8.1
     
  42. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Yes, it should be easy to fix, unless there are serious issues using reflexion on Windows Mobile (which I doubt since Unity seems to depend a lot on reflexion).
    Thank you for this. I hope Panda BT will come as an helpful tool for your University project. I have a look at your Youtube channel and your AI is playing the game in a convincing way.

    Thank you for your positive review on the Asset Store!

    If you want to go further with the pro edition and in case you want to try out the in-inspector editor before it is published on the Asset Store, just PM me and I would provide you with a beta package.
     
  43. andyblem

    andyblem

    Joined:
    Nov 11, 2014
    Posts:
    26
    Guys I need help on how I can implement this. I am fairly new t behavior trees and this is my first implementation. If you help with this part I think I would figure out the rest of my behaviors. The situation is like this, if the game is off all the players in a soccer field are supposed to look at the ball. If the game is off and a player is the KickOffSupporter he should constantly check if the "BallIsWithinReceivingRange", if the ball comes within this range, the player should "SetGameOn", "SetBallReceiver" to be the "KickOffBallReceiver" player. Now when the game is on each player should check if his team is in control or not. If his team is in control he should check if he is the "ClosestTeamMemberToBall", if he is he should check if the team has a ball receiver assigned to receive that ball. If its that case he can't continue to chase the ball. If there is no receiver assigned, the player checks if the ball is "WithinKickingRange" if not ChaseTheBall else "Shoot" if possible, "Pass" if shooting is impossible and passing is possible and if all this fails "Dribble". If there is a receiving player assigned the player has to check if he is the team's "BallReceiver", if he is he moves towards the pass target and if he is at the target he tracks the ball and if the ball comes within the receiving range he should stop and start traversing tee tree again.
    This is just part of the A.I, other further checks include checking if he is the supporting player, interposing player e.t.c
    Here is what I have done so far
    Code (CSharp):
    1. tree "Root"
    2.     fallback
    3.         while IsGameOn
    4.             tree "GameOn"
    5.         while not IsGameOn
    6.             tree "GameOff"
    7.  
    8. tree "GameOn"
    9.     fallback
    10.         tree "TeamInControl"
    11.         //tree "TeamNotInControl"
    12.  
    13. tree "TeamInControl"
    14.     //fallback
    15.     while TeamInControl
    16.         fallback
    17.             tree "IsClosestToBallTree"
    18.             tree "IsBallReceiverTree"
    19.             TrackBall
    20.         //tree "IsSupportingPlayerTree"
    21.         //tree "HasToRunIntoPlaceTree"
    22.  
    23. //tree "TeamNotInControl"
    24.  
    25. tree "IsClosestToBallTree"
    26.     sequence
    27.         IsReceivingPlayer 0.0
    28.         fallback
    29.             fallback
    30.                 not
    31.                     BallWithinKickingRange
    32.                 not
    33.                     CanShootBall
    34.                 ShootBall
    35.                 not
    36.                     CanPassTheBall 5.0
    37.                 PassBall
    38.                 Dribble
    39.             ChaseBall
    40.  
    41. tree "IsBallReceiverTree"
    42.     sequence
    43.         IsReceivingPlayer 1.0
    44.         fallback
    45.             not
    46.                 TeamInControl
    47.             fallback
    48.                 repeat
    49.                     sequence
    50.                         not
    51.                             AtTarget
    52.                         MoveToPassTarget
    53.                 repeat
    54.                     fallback
    55.                          not
    56.                             BallWithinReceivingRange
    57.                         Receive
    58.  
    59. tree "GameOff"
    60.     fallback
    61.         sequence
    62.             fallback  
    63.                 not
    64.                     IsKickOffSupporter
    65.             TrackBall
    66.         tree "IsBallWithinKickRange"
    67.      
    68.  
    69. tree "IsBallWithinKickRange"
    70.     fallback
    71.         not
    72.             BallWithinReceivingRange
    73.         StartGame
    74.  
    My Monobehaviour functions simply return a Succed or Fail dpending on the out come of the method
    My problem is I can't seem to make my the player receive the ball and start dribbling or passing the ball around. Seems like my tree gets stuck in the receive node. I am still new at this and I guess its a newbie error.

    Here is a snippet of my behaviour tree during game play.

    Before the Ball is within receiving range
    Before.PNG

    When the ball is now within receiving range
    After.PNG
     
  44. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Behaviour Tree is goal oriented; it's more declarative than procedural. That is, your describe your tree in term of what-to-do instead of how-to-do it.

    The overall structure of your current behaviour is based on the if-then structure. Which is natural for a programmer to think this way, but this habit can conflict with how you are supposed to think when building a behaviour tree.

    Try to think in term of actions (and sub-actions) and priorities, it will make things easier.

    You want to implement the behaviour for a soccer player. (Note that because of the nature of this game, it will result in a complex behaviour tree and it might not be the best type of game to start with to learn behaviour tree, but eh, who does not like a bit of challenge?).

    The top priority action for a soccer player is to score (action), that is to put the ball into the goal of the opposite team. If this action fails, for whatever reason, the next best thing to do is to keep the ball, if keeping the ball fail, which means the other team has the ball, then the next best thing to do is to defend. This is a fallback structure. So our top tree would look like this:
    Code (CSharp):
    1. tree "Root"
    2.     fallback
    3.         tree "Score"
    4.         tree "KeepTheBall"
    5.         tree "Defend"
    This is the high level (abstract) strategy. Then we can go down specifying each sub tree. What do we mean by scoring? We score by kicking the ball into the goal of the adversary, we can do this only if we have the ball and that there is a shooting trajectory to the goal. So the definition of this sub tree would be:
    Code (CSharp):
    1. tree "Score"
    2.     sequence
    3.         HasTheBall
    4.         HasShootingLineToGoal
    5.         KickBall_ToGoal
    And keep the ball would be something like this:
    Code (CSharp):
    1. tree "KeepTheBall"
    2.     sequence
    3.         HasTheBall
    4.         fallback
    5.             tree "Drible"
    6.             tree "Pass"
    From there, you can go down the tree by describing more and more concrete actions. Also, depending of the role of the player there might be variation in the definition of the low level sub-trees.

    I hope that this has somehow put you on track, and that you have a clearer idea about how to elaborate a behaviour tree.
     
    Last edited: May 7, 2016
  45. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
  46. andyblem

    andyblem

    Joined:
    Nov 11, 2014
    Posts:
    26
  47. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Enabling or disabling the Panda Behaviour component is done through the enabled property, as any other component. Maybe it's just a namespace issue; the PandaBehaviour class is under the Panda namespace.

    Code (CSharp):
    1. using Panda;
    2. // ...
    3. var pandaBehaviour = GetComponent<PandaBehaviour>();
    4. pandaBehaviour.enabled = true;
    5. // ...
     
  48. bendangelo

    bendangelo

    Joined:
    Nov 12, 2014
    Posts:
    9
    Hey, great library.

    Is it possible to dynamically add behaviour texts at run time? How can I do it?
     
  49. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Yes, it is.
    You can use strings as BT scripts and compile them at runtime through PandaBehaviour.Compile(...).
     
  50. bendangelo

    bendangelo

    Joined:
    Nov 12, 2014
    Posts:
    9
    I'm getting this weird error: PandaScriptException: Tree node has too many children. Only one is expected in file 'lala': line 1

    What does this mean? My tree looks like this:
    Code (CSharp):
    1. tree "BotTree"
    2.     sequence
    3.         IsBot
    4.         tree "Patrol"
    5.  
    6. tree "Patrol"
    7.     while
    8.         sequence
    9.             IsPatrolling
    10.             not FindTarget
    11.             not HasCommand
    12.     repeat
    13.         sequence
    14.             SetTargetWaypoint
    15.             MoveToWaypoint
    16.             Wait 0.3
    17.             NextWaypoint
    18.