Search Unity

AI: Behaviour trees in Unity: Behave 1.1 released

Discussion in 'Assets and Asset Store' started by AngryAnt, Sep 29, 2010.

  1. Eric

    Eric

    Joined:
    Nov 17, 2008
    Posts:
    20
    Many thanks for this library AngryAnt. Its a great way to improve my AI.

    I would be glad if you could answer me the following question:
    Is there a way to Tick the tree from another ID than the next ID that follows the regular tree logic?

    Say I have an agent that is on his way to go home. Now another agent interrupts his action by talking to him. After the dialog I want the first agent to complete his action of going home.

    So I have to know where the agent had been before he had been interrupted. For this case I could save the LastTicked value.
    My question is now how I could Tick the tree on this saved ID (after completion of the interrupting tasks) instead of the next logical step in the tree.

    Is this the correct way of thinking or is there another way of keeping the knowledge about the last action done before being interrupted?
    Hope I could explain it clear enough and thanks in advance for any help
     
    Last edited: Feb 12, 2011
  2. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    @ratamorph:
    This was brought to my attention recently. The current version of Behave unfortunately offers no solutions for collaboration on the same Behave asset. I am aware of the issue now and I've got some ideas on the drawing board. Until then, I'm afraid it'll have to be old-school "I've got the file now" collaboration.

    @Five Elements:
    I've seen people bring up similar issues before, but have not been able to reproduce myself. One suggestion would be to download and install the mono runtime. It is possible that in some cases Unity is unable to find its mono compiler when invoked via System.CodeDom.Compiler.

    @Eric
    That is indeed a bit backwards in the context of behaviour tree design. Generally, the tree should just react to whatever data it is fed by the agent. The agent should not interfere with tree execution other than providing that data, handling priority selectors and of-course ticking and resetting the tree.

    So let's say your agent was on his way to the super market when something interrupted him. A way to handle returning to the super market trip is to have a "mission" enum - dictating what the agent should be doing when not handling some interrupt state. You could set it up like this:

    Code (csharp):
    1. public enum Mission { None, Groceries, SaveTheWorld };
    2. private Mission m_CurrentMission;
    Actions:
    • MissionIsNone
    • MissionIsGroceries
    • MissionIsSaveTheWorld
    • SetMissionNone
    • SetMissionGroceries
    • SetMissionSaveTheWorld

    Use these mission checks to determine tree flow after exiting the "I'm busy talking" branch.

    Hardwiring execution order of a tree might be the hack you could use right now, but in the end it'll come back and bite you. Scenarios change and that hardwired location in the tree might not at all be the most sensible spot to return to after a conversation.
     
  3. Minassian

    Minassian

    Joined:
    Nov 22, 2010
    Posts:
    40
    Hey AA.
    Question.
    Are collections only for organizational purpuses ?
    If so, woulnd't make sense to allow linking subtrees from external collections ?
     
  4. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    I've set up a survey to better understand peoples use of Behave and uncovered needs. Please take a few minutes to complete the survey and help shape future releases of Behave: http://angryant.com/behave/survey/.

    @Minassian
    Collections are indeed only there to allow you to isolate trees from each-other. What is your use case for breaking this isolation?
     
  5. Minassian

    Minassian

    Joined:
    Nov 22, 2010
    Posts:
    40
    Hey AA.
    I thought that thats what different libraries where for.
    I'm starting up with AI so I'm not sure if I'm going in the right direction.
    I'm modelling a dinamic AI that responds to the world state (opposite from a sequential objective based AI).

    Best way I come up so far is having a parallel node with each different individual behaviours as childs.
    Each child is a selector that chooses which state that behaviour is in each point in time.
    It does so by ticking subtrees, which are actually sequences of conditionals that define if the agent is in that state.



    So for instance, right now I'm modeling an escort unit AI. The selector that chooses where that unit has to go has:
    Defend escortable conditional subtree: Checks if its escorting a unit, and if its being attacked and sets the state to pursue the attacker.
    Escort conditional subtree: Checks if there's no enemy units around and if its escorting a unit and sets the state to escort the escortable.



    Pursue enemy conditional subtree: Checks if there's an enemy in range and pursues it.
    Wander: If none of the other conditionals evaluated to success sets the state to wander around.

    Now, replying to your question this is a shortened and simplified version but as you can see it has two escortable specific subtrees and a subtree that can be reused by other type of units (pursue enemy conditional subtree) so I was thinking in having different collection for different types of units and a collection for generic subtrees like those one.

    Cheers.
     
  6. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    That's a good sell. I'll look into it.
     
  7. Eric

    Eric

    Joined:
    Nov 17, 2008
    Posts:
    20
    Thank you for your response AngryAnt, sounds good, now i'll do it the way you described.

    Before you have answered my question I thought about ticking the "Main"-Tree via a separate "Interruption"-Tree that just ticks the "Main"-Tree if the condition is true. This way I could keep the focus on the last Action of the "Main"-Tree, but I would have problems if the interrupted action cant handle the return to the main task (if the agent is playing a "sitting down" animation for example). So this way isn't really practicable.

    There are two more things, that keep me enganged (The first I already mentioned in your survey):

    1. If I have a Priority Selector that executes a Running child ("the Priority Selector will not re-query priority on the next tick") that has been interrupted by its parent (a selector that returns Failure by a condition for example), then the Priority Selector will not re-query priority if it is executed another time.



    2. I can't read Contexts that are specified in a subtree. If I log the ActiveContext from a component within a subtree I just get the context from the main tree and not the context in the subtree.

    At the moment this makes it difficult for me to make larger use of Priority Selectors.
    Did I find bugs or did I misunderstand something?

    Thanks
     
  8. Minassian

    Minassian

    Joined:
    Nov 22, 2010
    Posts:
    40
    Hey Eric.
    About 1)
    I've found priority selectors not fitting my needs for implementing state based AI too.
    I believe that the Runing return value is more aimed towards objective based AI since you have to either implement the condition to (fail or success) in code or do it by a parallel, in which case in my tests ended up repeating a lot of behaviour.
     
  9. Eric

    Eric

    Joined:
    Nov 17, 2008
    Posts:
    20
    Hi Minassian,
    you may be right, but what I don't understand is why Priority Selectors don't just behave like Sequences or Selectors when they are interrupted in case of having a Running child. If a Sequence has a Running child and its parent interrupts it, then the Sequence forgets its Running state the time it has been interrupted and restarts if it is executed again (same for Selectors). Why shouldn't Priority Selectors be able to behave the same way? In this case they would be able to handle state based AI too without making conflicts.
     
  10. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    Hey Eric

    The priority selector did indeed not reset correctly in Behave 1.2. This was not by design - definitely a bug and it has been corrected in Behave 1.3 which will be out soon.

    Regarding contexts, it's quite possible that I only pass it down to subtrees, but don't retrieve it back again. I'll look into it.

    I also plan to introduce named priority selectors. The component was basically just added in Behave 1.2 and I wanted to check out if people could make do with context alone (which was also just added in 1.2).

    I'm currently thinking of doing named priority selectors in the same style as Action and Decorator init/tick/reset:

    Code (csharp):
    1. public int SelectPriority (Tree sender, params int[] options)
    2. {
    3.     switch ((BLLibraryName.PrioritySelectorType)sender.ActivePrioritySelector) { /*...*/ }
    4. }
    5.  
    6. public int Select[Name]Priority (params int[] options)
    7. {
    8.     /*...*/
    9. }
    This is still right off the drawing board though, no promises.
     
  11. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    In other news, with the release of Path 2 and the pending upgrade of the Path - UnitySteer integration, I'll start work on a full-on AI example using all three systems.
     
  12. Eric

    Eric

    Joined:
    Nov 17, 2008
    Posts:
    20
    yeah! thats great to hear.
    I can't wait to use your new Behave release and to have a look at your AI example.
     
  13. Minassian

    Minassian

    Joined:
    Nov 22, 2010
    Posts:
    40
    That sounds great AngryAnt thanks.
     
  14. invulse

    invulse

    Joined:
    Nov 29, 2010
    Posts:
    128
    I am having some trouble understanding why decorators cannot return a Failure themselves, maybe someone can help me with this problem.


    Lets say I want to create a Selector that which tries its first branch which I want to have a Decorator on that determines initially whether or not we should even run its leaf Action, then if this Decorator fail move on to the next Branch and try that. However since a Decorator cannot ever return failure it seems like my only option to have this work is to have the functionality that the decorator has within my Action, but that seems counter-intuitive to me. Could someone enlighten me as to the best way to handle this?
     
  15. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    I just updated the Behave documentation to include a link to Bjoern Knafla's very nice introduction to behaviour trees, published for #AltDevBlogADay.

    http://angryant.com/behave/documentation/

    @invulse
    I'm not sure of your exact use case, but usually I cut off branches via actions on sequences with the subtree. IE: Sequence -> (Conditional action, Subtree).
     
  16. invulse

    invulse

    Joined:
    Nov 29, 2010
    Posts:
    128
    AngryAnt,

    I have been experimenting with using Parallel's on my main tree and I have noticed that when I use a parallel, on certain ticks, each of my branches attached to the parallel is ticked, but on the next if one of the branches has a selector on it and the selectors first branch failed, the parallel will only tick the branch with the selector that needs to move on to the next branch and no other branches of the parallel at all. Is this normal? From the short documentation in the Behave browser it sounds like the parallel should tick each of its branches on every tick.

    The problem this causes, is now certain actions that should run every tick sometimes get delayed 2-3 ticks, which causes a very noticeable delay in certain AI functions that should happen every tick.
     
  17. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    In 1.2, there is an issue with selectors properly being reset by parallels. I've got a fix for this in 1.3 which I will hopefully be able to ship this weekend.
     
  18. Minassian

    Minassian

    Joined:
    Nov 22, 2010
    Posts:
    40
    See the following example:
    Decorator:IsInRange -> Action:Attack



    Attack needs to know when to stop, and hardcoding it in IsInRange doesn't feel right since its out of its responsability.
    ResetAttaclAction doesn't seem to be executing when Decorator fails (enemy is not in range anymore).

    Is there a way for the childs to know when a decorator has returned a failure ?
     
    Last edited: Feb 27, 2011
  19. Minassian

    Minassian

    Joined:
    Nov 22, 2010
    Posts:
    40
    I kinda solved it with the same state conditional pattern I've been using for the rest of the behaviours.
    Which actually evolved in a small framework that I may publish if it gets polished enough.

    Just a thing, is Context working ?
    Cant settit on the editor.

    // Edit:
    Sorry, let me rephrase that: How can I define context enums to set them in the nodes ?
    // Edit:
    Gotit. No number as contexts.

    BTW AA I'm still getting the 'Invalid Data: Please go back and try again' message in you page, cannot register for the Behave beta.
     
    Last edited: Mar 2, 2011
  20. bruceh

    bruceh

    Joined:
    Mar 19, 2011
    Posts:
    1
    I'm having trouble figuring out how to implement an interrupt using a decorator. Reading the documentation, it seems that it's not possible for a decorator to return failure unless one of its children returns failure. Consider


    I want to fall back to Wander whenever IsEnemyNear returns failure. But there is no fallback since decorator failure is interpreted as success by the parent selector. Any ideas? I know I can achieve a similar result in other ways--actions can check for failure conditions, a sequence with a condition action--but this way seems more natural.

    AngryAnt, in your presentation on aigamedev, your behavior tree examples seem to use this pattern a lot, a selector with decorator interrupt children, so I assume it's possible but I'm missing something obvious.
     
  21. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    @Minassian:
    Thanks, yea I had forgotten about that. Need to fix my wordpress install somehow.

    @bruceh:
    Yea sorry about that in the video. Those trees were basically not correctly constructed. I quickly set them up an hour before the presentation, without trying them out. That was a pretty crazy weekend.

    Basically decorators are meant for interrupts and repeaters - not conditions. For your case I'd replace the decorator with a sequence and a conditional action after that - just before the evade action.

    Here's an example where I use decorators as interrupts:
     
  22. invulse

    invulse

    Joined:
    Nov 29, 2010
    Posts:
    128
    AngryAnt,

    Can you clarify if parallel's should tick each of their branches every tick regardless of what any of the other branches in the parallel have returned?

    In my BT I am noticing that parallels will hold up in a branch if one of the branches returns BehaveResult.Running, and will continue to only tick that branch until it has returned either fail or success. This seems to be the opposite of what you would want a parallel to do, as I have a set of 4 branches which MUST be ticked every AI tick or the behavior tree will run in to AI players simply not noticing that their gun is out of ammo, or not noticing that another enemy is actually closer to them than the one they are running towards, since those branches never get ticked while the character is advancing towards an enemy.

    Thanks
     
  23. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    That is expected behaviour. Parallels are not meant to function as interrupts. That's what decorators are for.
     
  24. invulse

    invulse

    Joined:
    Nov 29, 2010
    Posts:
    128
    Im confused so if that is the expected behavior of a parallel, how is it possible in a behavior tree to run multiple branches each tick that, will get run every single tick regardless of if other branches are currently returning running? Do I have to create multiple behavior trees for this functionality?
     
  25. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    If you want to have a branch to continuously repeat, regardless of return value, you should use a decorator.

    Decorators generally handle continuity in that you can use them either as loops or interrupts.

    Parallels ensure that all their children are ticked on the same AI frame. In the case of two continuously running children, parallels can be configured to interrupt one if the other finishes early.



    In the above example, I set the parallel to complete when one child has completed with success or failure and the RepeatWithTarget decorator implementation returns Running as long as a valid target is set.

    The GoToTarget implementation returns Running as long as the character has not arrived within range of the target.
     
  26. invulse

    invulse

    Joined:
    Nov 29, 2010
    Posts:
    128
    I finally understand what I was doing wrong, all I had to do was set the parallel to only require one child to complete and now it runs perfect. I didn't realize that when set to all, it has to wait for all branches to return complete in order to start ticking all of them again.
     
  27. Bugfoot

    Bugfoot

    Joined:
    Jan 9, 2009
    Posts:
    533
    I apologize if this isn't the best place to post this, but that was my best guess! :)

    First of all, thanks for developing this and making it freely available. It's an interesting concept and I think it would really speed up my game's AI development. I've got a couple of questions and comments regarding your library:

    - I think I remember you mentioning in one of the two video tutorials that when Behave instantiates a tree, it also uses reflection to lookup the custom Tick handlers methods (TickForward delegates) and automatically bind them to the tree actions with the same name. In my test, this is not the case, and I have to manually bind the delegate using tree.SetTickForward. Is there anything special I need to do on my Tick handlers to have them be properly picked up by the system without me needing to manually set them up?

    - Is there a way to leverage Unity's Coroutines inside tree actions, so that I can have an action that takes X seconds to complete and blocks the tree until it's done? A simple example would be a sequence with 3 actions: PrintX > Wait5Seconds > PrintY. I would like my Wait5Seconds action to block the tree execution for 5 seconds so that PrintY will be called 5 seconds later. Ideally, I would implement my action with a yield return new WaitForSeconds(5). Clearly that won't work with the current framework as TickForward delegates do not return an IEnumerator and thus can't be used as coroutines. What's the best way to do that in the leanest cleanest way?

    - Please take the following as constructive criticism: the documentation and video tutorials are quite poor and could use a lot of love. For instance, in the first video, you probably spend half your time typing in random funny comments in the tree blocks, which is not extremely useful to someone new to your system. Also the sample project is very outdated and doesn't run on Unity 3. I tried to fix some of the namespace collision errors, but then ran in more problems and gave up.

    Thanks for your hardwork, and im looking forward to getting more familiar with behaviour trees as they seem like the right tool for my game's AI needs :)
     
  28. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    @Spk:
    It sounds like you are not naming the handlers correctly. See the IAgent documentation for details on the exact naming. Alternatively you could have made them private or protected. Notice that auto-connect handlers *must* be public.

    Coroutines would not be needed for what you describe. That is the point of the Running return value.

    The documentation could indeed use a lot of work. With regards to the example project, you should be aware of the compatibility level specified for each download. The Editor demo project is *not* 3.x compatible.
     
  29. Erick

    Erick

    Joined:
    Mar 21, 2011
    Posts:
    14
    If i have like 3 different decorators(or actions ...), with the same name in a tree, how can I know witch one is ticking inside my tick function?

    I was trying to implement a Loop decorator and realized i could not know witch counter to increment.
     
  30. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    What I do for my loop decorator I store the counts in a string-int dictionary - using the string parameter of the tick to access the correct counter. The float parameter you could use for specifying the number of iterations to run.

    If you haven't spotted them yet, the string and float parameters can be set in the inspector when a decorator or action is selected.

    Example (untested):
    Code (csharp):
    1. Dictionary<string, int> m_Counters = new Dictionary<string, int> ();
    2.  
    3. public BehaveResult InitRepeaterDecorator (Tree sender, string counter, float max, IAgent agent, object data)
    4. {
    5.     if (!m_Counters.ContainsKey (counter))
    6.     {
    7.         m_Counters[counter] = 0;
    8.     }
    9.  
    10.     if (++m_Counters[counter] > max)
    11.     {
    12.         return BehaveResult.Failure;
    13.     }
    14. }
    15.  
    16. public BehaveResult TickRepeaterDecorator (Tree sender)
    17. {
    18.     return BehaveResult.Running;
    19. }
    20.  
    21. public void ResetRepeaterDecorator (Tree sender, string counter, float max, IAgent agent, object data)
    22. {
    23.     m_Counters[counter] = 0;
    24. }
     
  31. pimthegreat

    pimthegreat

    Joined:
    Aug 15, 2010
    Posts:
    7
    Hi, I've just recently started using Behave and I've had this problem i could figure out. In any connection I make to a priority selector it gets listed as "Unknown component type". The sequencer works, I've tried using it and switching priorities and making a simple Debug.Log() to try it out. There is some funcions of behave that doesn't work thou, for example I can't form a subtree of a branch containing priority selectors.

    When i try to form a subtree I get some warnings concerning that the BehaveAsset and BehaveEditor must be instantieted using ScriptableObject.CreateInstance
    and the Action "Loading Behave library" seems to fail to process past these folowing lines before an "ArgumentExeption: Unknown Component Type" is thrown.
    Behave.Editor.Editor:set_Asset(IBehaveAsset)
    BehaveMenu:EditLibraryAsset(BehaveAsset) (at Assets/Behave/Editor/BehaveMenu.cs:196)
    BehaveMenu:EditLibrary() (at Assets/Behave/Editor/BehaveMenu.cs:19)
    BehaveMenu:Create() (at Assets/Behave/Editor/BehaveMenu.cs:80)

    I've done clean installs without errors and the problem persists. I'm running the latest version of Unity basic on a Windows 7 64 bit platform.

    Is this a known issue? Is there a fix for it?
     
  32. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    @pimthegreat
    The warning is harmless and is therefore not at the top of my todo list. The "Unknown component type" is also harmless, but annoying. It is fixed in the next release of Behave.
     
  33. pimthegreat

    pimthegreat

    Joined:
    Aug 15, 2010
    Posts:
    7
    Ah allright, nothing to worry about then. Thanks for the reply and your continued dedication towards Behave :)
     
    Last edited: Apr 6, 2011
  34. Bugfoot

    Bugfoot

    Joined:
    Jan 9, 2009
    Posts:
    533
    Could you elaborate on this please? I searched through the doc and could not find any references to a "Running" property or return value. Which class is this available on? What does it mean? How do you use it?

    Thanks

    EDIT: ok i've found it :p It's BehaveResult.Running. So I suppose you return this until you're done performing an action?
     
    Last edited: Apr 7, 2011
  35. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    Right on. See example usage in my response about a repeater decorator :)
     
  36. cupsster

    cupsster

    Joined:
    Apr 14, 2009
    Posts:
    363
    Hi all,
    I would like to ask someone to enlight me or for kind advice from start to finish how to deal with this example tree that I prepared for this "tutorial". Please I'm javascript oriented. I would like to to know HOW this is EXACTLY written in java so i can understand which variables go where.

    Thank you anybody which can provide that.
    For make it more friendly to write (compiled Info):
    Code (csharp):
    1.  
    2. Library class:
    3. BLNewBehaveLibrary0
    4.  
    5. Trees:
    6.     TestCollection_Patrol
    7.     Unknown
    8.  
    9. Contexts:
    10.     NavigateAround
    11.     SelectorTest
    12.     Locate
    13.     Unknown
    14.  
    15. Branch priority groups:
    16.     Unknown
    17.  
    18. Actions (4: 1 - 5):
    19.     startAtack (1)
    20.     lookAtThreatDirection (2)
    21.     observeArea (3)
    22.     patrol (4)
    23.     Unknown (5)
    24.  
    25. Decorators (3: 6 - 9):
    26.     isDisturbed (6)
    27.     suspiciousLevelHigh (7)
    28.     knowFightTarget (8)
    29.     Unknown (9)
    30.  
    I can learn code well but I need example in language I understand :) not foobar nor class/methods definitions. Other than bleeding documentation Behave is great! :)

    First of ALL:
    How to properly instantiate and initialize my tree in javascript?
     

    Attached Files:

    Last edited: Apr 8, 2011
  37. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    I'm not exactly a JS guru, but something like this:

    Code (csharp):
    1. // MyAgent.js //
    2.  
    3.  
    4. import Behave.Runtime;
    5. import Tree = Behave.Runtime.Tree;
    6.  
    7.  
    8. class MyAgent extends MonoBehaviour implements IAgent
    9. {
    10.     var tree : Tree;
    11.  
    12.  
    13.     function Start ()
    14.     {
    15.         tree = BLNewBehaveLibrary0.InstantiateTree (BLNewBehaveLibrary0.TreeType.TestCollection_Patrol, this);
    16.     }
    17.    
    18.    
    19.     virtual function Tick (sender : Tree, init : boolean) : BehaveResult
    20.     {
    21.         return BehaveResult.Success;
    22.     }
    23.    
    24.    
    25.     virtual function Reset (sender : Tree)
    26.     {
    27.        
    28.     }
    29.    
    30.    
    31.     virtual function SelectTopPriority (Tree sender, int[] IDs) : int
    32.     {
    33.         return IDs[0];
    34.     }
    35. }
     
  38. GFX47

    GFX47

    Joined:
    Dec 7, 2010
    Posts:
    124
    Hi,

    I'm pretty new with behavior trees and especially with Behave so forgive me if my questions sound stupid to you guys.


    I don't understand why (in Behave) decorators return Success when the tick method returns Failure.
    I thought decorators were meant to "override" sub-stree's return value to enable more complex features like event listening, filters, interrupters or even loops.

    In this case (always returning Success or Running), I don't see how to make a decorator return Failure and use any upper-level selector to give the opportunity to fallback sub-trees to be ticked.

    Is this the standard behavior of decorators in behavior trees or is it specific to Behave?


    I also noticed that you often use combinations of sequences+decorators to implement interrupters where others (like guys from aigamedev.com) would use selectors+parallel branches to listen to interrupting events.

    Is it a consequence of the way decorators work in Behave or is there some kind of optimization hidden behind it?

    Oh and 3rd question: how can I delete or modify a link between 2 components in Behave editor (without deleting one of the components)?

    Thanks a lot for your answers.

    PS: you could add "or did I miss something" to all of my questions ^^
     
    Last edited: Apr 26, 2011
  39. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    You are not the first to find this setup confusing, but basically this is a point where having decorator and action handlers being so similar is a disadvantage. The problem is that the return value of a decorator tick method does not translate to return value - like action handlers do. In stead the return value of decorator handlers is sent to the decorator component - signaling interrupt or repeat.

    With a decorator component selected, see the inspector for a more in-depth description of how values are handled in the component.

    Most other systems implement decorators as supporting interrupt only (no repeat). This frees up the full resolution of return values from the decorator.

    Currently Behave 1.3 is sitting in the AssetStore submission pipes - holding various fixes and additions. For Behave 1.4 I am focusing on making decorators easier to understand and use.

    That is pretty much design preference.

    When a component with outputs is selected, you can reorder and remove connections in the inspector. I realize this is not very clear, so in 1.3 (which as mentioned is just pending asset store review), I am moving these functions out of the inspector and into the tree editor.
     
  40. GFX47

    GFX47

    Joined:
    Dec 7, 2010
    Posts:
    124
    Thanks for you answer!
    I did read the decorator specifications in inspector and that's why I asked :)

    Another question btw:
    When the tick of a decorator returns Running, the decorator will return Running whatever it's child returns.
    I guess it's how repeater has to be implemented.
    But in this case, how can you ever get out of the loop (as the tree will always go back to the decorator on each tick)?
     
  41. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    By returning failure (break, don't tick the child and return success) or success (tick the child and return whatever it returned).

    I wrote an example implementation just above.
     
  42. GFX47

    GFX47

    Joined:
    Dec 7, 2010
    Posts:
    124
    Sorry, my question was not that clear, I meant breaking the loop from the child node.
    Like implementing "loop until my child returns failure" for instance, typically for some event listening.
     
  43. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    Event listening is exactly what a decorator would be good for. But as explained above, it would be the decorator tick handler dictating when to interrupt, not the child node.
     
  44. GFX47

    GFX47

    Joined:
    Dec 7, 2010
    Posts:
    124
    Ok I think I got it now, testing it right now.Thanks again very much for your help.

    [Switching to Columbo mode now ^^]

    You didn't answer one of my questions, sir: does this implementation (meaning the whole decorator return vs tick return vs child return) match the standard definition of decorators in behavior trees theory or is it specific to Behave?
     
  45. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    I did.

    Please read the thread and my direct answers before posting. This thread is getting quite long and full of repeats.
     
  46. GFX47

    GFX47

    Joined:
    Dec 7, 2010
    Posts:
    124
    Oh I read it all, I just didn't think it answered completely to my question, that's why I precised "the whole decorator return vs tick return vs child return".
    Anyway thanks and good luck for your asset store submission btw :)
     
    Last edited: Apr 28, 2011
  47. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    After quite a long break (including shifting around at utech, doing a Path release etc.), Behave is finally getting another update!

    This release is primarily a bugfix and editor polish release. One thing I'd like to highlight though is the addition of agent blueprints. From the changelog:

    Generally this enables you to more explicitly tie up handlers and cuts down on tree initialization time. Oh and of-course you gain auto-completion when setting up your handlers.

    Anyway, here's the whole changelog:

    1.3:
    - Fixed priority selector init flag resetting.
    - Fixed reference handling on tree renaming and deletion.
    - Fixed references still pointing at old collection post collection duplication.
    - Fixed compilation of actions and decorators with non-integral float parameters.
    - Fixed GUI list behaviours.
    - Fixed passing context back and forth between referenced trees and referrer.
    - Fixed reordering connections not causing save state to be set.
    - Various GUI tweaks.
    - Runtime optimisations.
    - Enabled scrolling of the tree list in the debugger window.
    - Exposed Tree.ReflectForwards.
    - Added Tree.ResetForwards.
    - Added agent blueprints - connecting to agent handlers through virtual methods rather than reflected handlers.
    - Made connections selectable in the tree editor via the connection nub.
    - Moved connection managing from the inspector to the tree editor, where it is more visible and handy.
    - Added support for disabling connections - for faster, less destructive debugging.
    - Double-click reference component to jump to referenced tree.
    - Changed "Cannot update unregistered tree" handling from an exception to an error message. Still need more info.
    - Now showing string and float parameters in the tree editor if either is set.</pre>

    You'll find a link to the package in the download section. Have fun!

    Blog post.
     
  48. samim

    samim

    Joined:
    Jan 4, 2009
    Posts:
    13
    @AngryAnt: Very cool stuff! Thanks allot for the updated. If been living inside behave for the last 3 weeks and have found it a very enjoyable and enlightening experience.
     
  49. GFX47

    GFX47

    Joined:
    Dec 7, 2010
    Posts:
    124
    Nice update on the tree editor ergonomy.
     
  50. bryanleister

    bryanleister

    Joined:
    Apr 28, 2009
    Posts:
    130
    I don't know if this is related to the update or not, but I've tried a few times to get your examples up and running but ran into errors either with the examples of one kind or another. I'm determined to get this working though this time and start learning how to use a BT.

    I have copied the code from your video exactly, but I get this error:

    Assets/AgentAwesome.cs(7,14): error CS0535: `AgentAwesome' does not implement interface member `Behave.Runtime.IAgent.Tick(Behave.Runtime.Tree, bool)'

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using Behave.Runtime;
    4. using Tree = Behave.Runtime.Tree;
    5.  
    6.  
    7. public class AgentAwesome : MonoBehaviour, IAgent
    8. {
    9.     Tree m_Tree;
    10.  
    11.     // Use this for initialization
    12.     IEnumerator Start ()
    13.      {
    14.         m_Tree = BLNewBehaveLibrary0.InstantiateTree(
    15.             BLNewBehaveLibrary0.TreeType.NewCollection1_myMagicTree,
    16.             this
    17.         );
    18.        
    19.         while (Application.isPlaying  m_Tree != null)
    20.         {
    21.             yield return new WaitForSeconds (1.0F / m_Tree.Frequency);
    22.             AIUpdate();
    23.         }
    24.    
    25.     }
    26.  
    27.  
    28.     void AIUpdate ()
    29.     {
    30.         m_Tree.Tick();
    31.     }
    32. }
    33.  
    I was able to Build the tree as a Debug build, so I think I'm pretty close. Any advice?