Search Unity

NodeCanvas - (Behaviour Trees | State Machines | Dialogue Trees)

Discussion in 'Assets and Asset Store' started by nuverian, Feb 8, 2014.

  1. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hello,
    I managed to replicate the log coming up to the console in the specific case -like you said- where the GlobaBlackboard is a prefab and only when building the game. Even though it is false positive error and everything should still work fine in-game, to very quickly fix it from coming up, please open up GlobalBlackboard.cs and add the following lines of code at the very start of both the "Awake()" and "OnValidate()" functions of the class.
    Code (CSharp):
    1.             #if UNITY_EDITOR
    2.             if (UnityEditor.EditorUtility.IsPersistent(this)){
    3.                 return;
    4.             }
    5.             #endif
    Please let me know if that solves it for you.
    Thank you and sorry for the late reply!
     
  2. DarkMasster

    DarkMasster

    Joined:
    Mar 23, 2015
    Posts:
    15
    Hi nuverian !

    Can you add additional events for Variables< List< T > >, who was dispatched then collection was get or removed new elemets. Or may be new type - VariableCollection< T >. That be very helful *))))

    Example events:

    OnAddItem;
    OnAddRange;
    OnClear;
    OnElementChange;
    OnRemoveItem;



    Example list from one my project:

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. namespace CrazyPanda.UnityCore.NotifierTypes
    6. {
    7.     public class NotifierList< T > : IList< T >
    8.     {
    9.         #region Private Fields
    10.         private List< T > _list;
    11.         private object _sender;
    12.  
    13.         private GenericEventArg< IEnumerable< T > > _onAddRangeArgs;
    14.         private GenericEventArg< IEnumerable< T > > _onClearArgs;
    15.         private GenericPairEventArgs< int, T > _onAddItemArgs;
    16.         private GenericPairEventArgs< int, T > _onElementChangeArgs;
    17.         private GenericPairEventArgs< int, T > _onRemoveArgs;
    18.         #endregion
    19.  
    20.         #region Properties
    21.         public int Count
    22.         {
    23.             get { return _list.Count; }
    24.         }
    25.  
    26.         public bool IsReadOnly
    27.         {
    28.             get { return false; }
    29.         }
    30.  
    31.         public T this[ int index ]
    32.         {
    33.             get { return _list[ index ]; }
    34.             set
    35.             {
    36.                 _list[ index ] = value;
    37.                 FireOnElementChange( value, index );
    38.             }
    39.         }
    40.         #endregion
    41.  
    42.         #region Constructors
    43.         public NotifierList() : this( 0, null )
    44.         {
    45.         }
    46.  
    47.         public NotifierList( object sender ) : this( 0, sender )
    48.         {
    49.         }
    50.  
    51.         public NotifierList( int count ) : this( count, null )
    52.         {
    53.         }
    54.  
    55.         public NotifierList( int count, object sender )
    56.         {
    57.             _list = new List< T >( count );
    58.  
    59.             _onAddRangeArgs = new GenericEventArg< IEnumerable< T > >();
    60.             _onClearArgs = new GenericEventArg< IEnumerable< T > >();
    61.             _onAddItemArgs = new GenericPairEventArgs< int, T >();
    62.             _onElementChangeArgs = new GenericPairEventArgs< int, T >();
    63.             _onRemoveArgs = new GenericPairEventArgs< int, T >();
    64.  
    65.             _sender = sender ?? this;
    66.         }
    67.         #endregion
    68.  
    69.         #region Public Members
    70.         public event EventHandler< GenericPairEventArgs< int, T > > OnAddItem;
    71.         public event EventHandler< GenericEventArg< IEnumerable< T > > > OnAddRange;
    72.         public event EventHandler< GenericEventArg< IEnumerable< T > > > OnClear;
    73.         public event EventHandler< GenericPairEventArgs< int, T > > OnElementChange;
    74.         public event EventHandler< GenericPairEventArgs< int, T > > OnRemoveItem;
    75.  
    76.         public IEnumerator< T > GetEnumerator()
    77.         {
    78.             return _list.GetEnumerator();
    79.         }
    80.  
    81.         public void AddRange( List< T > collection )
    82.         {
    83.             _list.AddRange( collection );
    84.             FireOnAddRange( collection );
    85.         }
    86.  
    87.         public void AddRange( IEnumerable< T > collection )
    88.         {
    89.             _list.AddRange( collection );
    90.             FireOnAddRange( collection );
    91.         }
    92.  
    93.  
    94.         public void AddRange( NotifierList< T > collection )
    95.         {
    96.             _list.AddRange( collection );
    97.             FireOnAddRange( collection._list );
    98.         }
    99.  
    100.         public void Add( T item )
    101.         {
    102.             _list.Add( item );
    103.             FireOnAddItem( item, _list.Count - 1 );
    104.         }
    105.  
    106.  
    107.         public void Clear()
    108.         {
    109.             if( OnClear != null )
    110.             {
    111.                 var clearedElements = new List< T >( _list.Count );
    112.                 clearedElements.AddRange( _list );
    113.                 _list.Clear();
    114.                 FireOnClear( clearedElements );
    115.             }
    116.             else
    117.             {
    118.                 _list.Clear();
    119.             }
    120.         }
    121.  
    122.         public bool Contains( T item )
    123.         {
    124.             return _list.Contains( item );
    125.         }
    126.  
    127.         public void CopyTo( T[ ] array, int arrayIndex )
    128.         {
    129.             _list.CopyTo( array, arrayIndex );
    130.         }
    131.  
    132.         public bool Remove( T item )
    133.         {
    134.             var containsItem = _list.Contains( item );
    135.             if( containsItem )
    136.             {
    137.                 var index = _list.IndexOf( item );
    138.                 _list.Remove( item );
    139.                 FireOnRemoveItem( item, index );
    140.             }
    141.             return containsItem;
    142.         }
    143.  
    144.         public int IndexOf( T item )
    145.         {
    146.             return _list.IndexOf( item );
    147.         }
    148.  
    149.         public void Insert( int index, T item )
    150.         {
    151.             _list.Insert( index, item );
    152.             FireOnAddItem( item, index );
    153.         }
    154.  
    155.         public void RemoveAt( int index )
    156.         {
    157.             var removedItem = _list[ index ];
    158.             _list.RemoveAt( index );
    159.             FireOnRemoveItem( removedItem, index );
    160.         }
    161.         #endregion
    162.  
    163.         #region Private Members
    164.         private void FireOnAddItem( T item, int index )
    165.         {
    166.             if( OnAddItem != null )
    167.             {
    168.                 _onAddItemArgs.Key = index;
    169.                 _onAddItemArgs.Value = item;
    170.                 OnAddItem( _sender, _onAddItemArgs );
    171.             }
    172.         }
    173.  
    174.         private void FireOnRemoveItem( T item, int index )
    175.         {
    176.             if( OnRemoveItem != null )
    177.             {
    178.                 _onRemoveArgs.Key = index;
    179.                 _onRemoveArgs.Value = item;
    180.                 OnRemoveItem( _sender, _onRemoveArgs );
    181.             }
    182.         }
    183.  
    184.         private void FireOnAddRange( IEnumerable< T > items )
    185.         {
    186.             if( OnAddRange != null )
    187.             {
    188.                 _onAddRangeArgs.Value = items;
    189.                 OnAddRange( _sender, _onAddRangeArgs );
    190.             }
    191.         }
    192.  
    193.         private void FireOnElementChange( T item, int index )
    194.         {
    195.             if( OnElementChange != null )
    196.             {
    197.                 _onElementChangeArgs.Key = index;
    198.                 _onElementChangeArgs.Value = item;
    199.                 OnElementChange( _sender, _onElementChangeArgs );
    200.             }
    201.         }
    202.  
    203.         private void FireOnClear( IEnumerable< T > items )
    204.         {
    205.             if( OnClear != null )
    206.             {
    207.                 _onClearArgs.Value = items;
    208.                 OnClear( _sender, _onClearArgs );
    209.             }
    210.         }
    211.         #endregion
    212.  
    213.         #region Interface Implementations
    214.         IEnumerator IEnumerable.GetEnumerator()
    215.         {
    216.             return GetEnumerator();
    217.         }
    218.         #endregion
    219.     }
    220.  
    221.  
    222.     public class GenericPairEventArgs< TKey, TValue > : GenericEventArg< TValue >
    223.     {
    224.         #region Public Fields
    225.         public TKey Key;
    226.         #endregion
    227.  
    228.         #region Constructors
    229.         public GenericPairEventArgs()
    230.         {
    231.         }
    232.  
    233.         public GenericPairEventArgs( TKey key, TValue value ) : base( value )
    234.         {
    235.             Key = key;
    236.         }
    237.         #endregion
    238.     }
    239.  
    240.     public class GenericEventArg< TValue > : EventArgs
    241.     {
    242.         #region Public Fields
    243.         public TValue Value;
    244.         #endregion
    245.  
    246.         #region Constructors
    247.         public GenericEventArg()
    248.         {
    249.         }
    250.  
    251.         public GenericEventArg( TValue value )
    252.         {
    253.             Value = value;
    254.         }
    255.         #endregion
    256.     }
    257.  
    258. }
    259.  
     
  3. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hello :)

    Just to clarify, do you mean to change the default type used for collections in Blackboard Variables, from being List<T>, to a custom List implementation (like one posted) for the purpose of providing such events?

    Thanks.
     
  4. DarkMasster

    DarkMasster

    Joined:
    Mar 23, 2015
    Posts:
    15
    Hi !

    Yes, i think it's only one way to do than - create a new generic type, who implement IList<T>. And add some nice functionality, like additional events.

    May be need add something like Dictionary with events and ActionTasks. When i develop my projects - in many cases, i wanna use key-value pairs. Its very useful. *)))) If need i can attach exemple my realization for NotifierDictionary< TKey, TValue >.
     
  5. Deleted User

    Deleted User

    Guest

    Hey all, if you have a behaviour tree that sets an enemy to patrol, and then you need that enemy to follow the player when it gets in range to charge, attack, etc, but also have another very similar enemy that also patrols yet does something slightly different (perhaps stand still and charge later on for example), how would you go about handling that strategy within NodeCanvas?

    So far I've come up with just theories, not even sure if it's possible or a good idea. One being that you have multiple behaviour trees that handle each action, and you switch them out at runtime depending on some form of logic for that particular entity type, or, you just make a particular tree for each different type of enemy.

    I can't help but wonder if I'm overthinking it...

    Thanks!
     
    username132323232 likes this.
  6. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hello and sorry for late replies due to summer vacation.

    Hey,
    I have replied to your question in the NodeCanvas forums! :)
    Please let me know if that works for you here.
    Thanks!

    Hey,

    One way (probably the more straightforward one) to slightly change how multiple agents using the same graph are behaving, is to use different blackboard variable for each of those agents, to "parametrize" the graph accordingly.
    You could have a different branch for each possible different behavior and alter which branch is followed with for example, a Switch Composite node.
    SwitchComposite.png
    In this case the Switch Composite is set to work with an integer, but it can also be set to work with an enum if you prefer. The 3 different branches, could also be replaced with 3 different SubTrees if you like as well.


    Another way to make various agents using the same base BT, behave differently in some occasions, is (like you said), to use a different SubTree for each of them as required.
    The easier way to work with this, would be to make the SubTree node read the SubTree from a blackboard variable, which is very possible since the Behaviour SubTree can also be "parametrized" normally and through a variable as shown in the image bellow after the radial button is pressed. As such, in runtime, or in editor, you only need to change the blackboard variable named "Subtree" in this example, to point to the SubTree asset you want the agent to use in place.
    SubTreeParameter.png


    Finally, if the agents are very different from one another and none of the above solutions sound like a good one, then probably the best solution in that case, would be to indeed have them use a different BT altogether :)

    Please let me know if the above were helpful to you, or if you have any questions at all.
    Thanks!
     
    TeagansDad and Deleted User like this.
  7. Deleted User

    Deleted User

    Guest

    Good morning nuverian! Hope you had an awesome vacation :) Many thanks for your suggestions, they're absolutely bang on. The first option is probably the best for my situation, and what's more it's almost a work of art looking at it (this is why I love behaviour trees, they look freakin' sweet). :p

    Each different entity could quite seamlessly move to another state depending on certain environmental variables as mentioned, which would be more than enough for its needs. For the most part they'll be getting punted in the face shortly after it anyway, so it wont get too advanced.

    Boss-wise (just a random thought), I believe a similar approach could quite easily be taken. If we're looking at patterned movement for example, there's no reason why it couldn't work in a similar way (such as checking whether a certain pattern has been completed, change state to next phase, etc).

    Anyway! Just some clarification there (I also just had a coffee, so the words are falling out of my mind right now).

    Thanks again mate!
     
    nuverian likes this.
  8. username132323232

    username132323232

    Joined:
    Dec 9, 2014
    Posts:
    477
    Thanks! I got your response. BTW, it seems that NodeCanvas forums are more convenient than this forum since every question gets its own thread.

    Welcome back. We missed you here :)
     
    nuverian likes this.
  9. TonanBora

    TonanBora

    Joined:
    Feb 4, 2013
    Posts:
    493
    Not sure what I am doing wrong, but for some reason I keep getting this Debug Error:

    (Target Sensor) 'Can See Target' Task Error: 'Failed to resolve Agent to requested type 'UnityEngine.Transform', or new Agent is NULL. Does the Agent has the requested Component?' (Task Disabled)

    But I have no clue what it means.
    Here is the relevant branch of the BehaviorTree this occurs in: 2017-08-29_16-07-41.png
    It is happening at the condition in the middle of the picture, the one with:
    If (ALL True)
    * If Can See $target
    If "Health" > 0

    $target is not null when it reaches the Can See check, so I am not sure what is going wrong. :confused:
     
  10. TonanBora

    TonanBora

    Joined:
    Feb 4, 2013
    Posts:
    493
    Anyone have an idea on how to get the triggers to work like, well, triggers?
    I have tried using the If TriggerEnter condition, but it only triggers for single objects at a time.
    For example, when I place multiple objects inside a trigger, and press play, only a single object is picked up by the trigger. How would I get the trigger to pick up ALL objects like a normal coded trigger would?


    Should I simply just code my own trigger script, and have it interact with the BlackBoard, or is there a way to achieve this with Node Canvas?
     
  11. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    You are very welcome and thanks as well for the thorough follow up and clarification! :)


    Thank you!
    Yes, the NodeCanvas forums are indeed for convenient for support and discussions exactly for that reason you mention :)


    Hello,

    This error is telling us that the agent which is to be checked whether or not it can see $Target, is null when the condition is checked. By default the agent is "Self", but it looks like that you have overridden the agent (instead of being "Self") in the condition's inspector panel, through the checkbox as shown in the red rectangle in the screenshot bellow.
    AgentOverride.png

    Can you please confirm that you have assigned a transform (or variable) there, and that it is not null when the condition is checked.

    Please let me know.
    Thanks!

    Hello,
    Hmm. Can you please explain what you mean by saying that only one object is picked up?
    If say for example you have a BoxCollider trigger with an "If Trigger Enter" condition, then whenever any collider object has entered that collider trigger, the condition will return true.
    Can you please provide a few more details?
    Thank you in advance.
     
  12. a-t-hellboy

    a-t-hellboy

    Joined:
    Dec 6, 2013
    Posts:
    180
    Hey NodeCanvs developers,

    Thanks for amazing tool

    Is there any way to find out in script what the child of current node is ?

    Edit: I'm not sure if I use correct method. btw, I added a function that return currentNode in DialogueTree.cs and after that by using GetChildNodes() try to get child of current node.

    Now I want to know there is any way to find out if child node is multi choice or not ? for now I give a tag to the multi choice nodes but I want to know there is any easier way to find out if child node is multi choice or not.
     
    Last edited: Sep 10, 2017
  13. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    94
    <b>(Type Request)</b> Type with name 'NodeCanvas.Tasks.Actions.PlayAnimationSpine' could not be resolved.

    This happened after purging a bunch of old scripts I'm not using from a project.

    I know this can result from nodes tied to methods, but I only have 2 FSMs in my entire game and no Behaviour Trees and can't see why this would be attempting to be called when I start my game. I like to hard stop during QA if there are errors, so I'd like to figure out why this is happening.

    Somehow there's a nested FSM under one of my prefabs and I can't seem to figure out how to delete it. There's no little "person" icon next to the asset or any way I can see to purge it. Not sure if this is causing the problem, but I deleted every node from the FSM and it still continues.

    Edit, got the orphaned BT out of the game by dragging the prefab into my assets and deleting the old one. Problem wasn't that one and still persists... so now just 1 FSM and definitely no nodes tied to PlayAnimationSpine.
     
    Last edited: Sep 11, 2017
  14. zeb33

    zeb33

    Joined:
    Nov 17, 2014
    Posts:
    95
    Does the 'FromAnyState' node still exist? (I can't find it!)
    Screen Shot 2017-09-11 at 09.52.26.png
     
  15. zeb33

    zeb33

    Joined:
    Nov 17, 2014
    Posts:
    95
    ah,, FSM not BT..doh!
     
  16. Tyrameia

    Tyrameia

    Joined:
    Oct 9, 2015
    Posts:
    1
    Hello,
    my nested FSM (NodeCanvas 2.6.3) seems to sometime(usually works) completely skip a certain action state, as it would end without even running the OnExecute function. Is there any reason or problem that could make it act like that?

    1] The nested FSM 2] Start of skiped action state 3] just next in sequence action state 4] output only showing debuglog from the previous action state and then next in sequence
    Nový obrázek.jpg Nový obrázek (2).jpg Nový obrázek (1).jpg log.jpg
     
  17. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hey,

    Thanks a lot! I am glad you like NodeCanvas and sorry for the late reply.
    Using the GetChildNodes() on the currentNode, like you did, is the easiest way to get all child nodes of any other node.
    The best way to test if a node is of a certain type, would be to just use the "is" operator, like for example:
    if (currentNode is MultipleChoiceNode){ ... } :)

    Let me know if that works for you, or if you have any other questions.
    Thanks again!

    Hey!

    Sorry for the late reply. Hmm, a type resolution like this can occur either because a graph is using that type, a blackboard variable is of that type, or the type has previously been added in the Preferred Types editor.
    Do you by any chance, have added that now missing type in the Preferred Types list editor for any reason?
    Could there be any Asset Graph anywhere else in your project that still "reference" that type?

    Please let me know.
    Thanks!


    :)


    Hey,

    Is the output log shown here, based on the order in which the actions are shown in the first image ("Move Enemy" first, "Output Check" second) ?
    I am asking this because I've noticed that you've set the actions to "Run In Sequence" which means that one action will run after the other as soon as the previous one has finished, but your "Move Enemy" action never calls "EndAction()" as far as I can see, and as such it is never finished, thus in that case the second action "Output Check" would have never been called.

    The only way that the "OnExecute" call of an action in the list should be able to be skipped, would be either because:
    A) A previous action in the list has failed by an 'EndAction(false)' call.
    B) The actions are set to "Run In Sequence" and a transition happens before the action in question had a chance to execute (because previous actions in the list were still running).

    Please let me know if the above help in determining why this happens for you.
    Also if you are able to tell me any way to reproduce this, or even send me a project that does so, that would greatly help.

    Thank you!
     
  18. a-t-hellboy

    a-t-hellboy

    Joined:
    Dec 6, 2013
    Posts:
    180
    I have 2 parallel task in one dialogue tree node, each task has different actor, I want to know is there any way to assign actor to each task and run them in parallel. It is rational each task in a dialogue tree node has different actor but there is just one actor for bunch of parallel action tasks.

    Or maybe is there another way to run multi parallel action tasks in dialogue tree ?
     
  19. DeepShader

    DeepShader

    Joined:
    May 29, 2009
    Posts:
    682
    Hello,
    I'm thinking of buying NodeCanvas w/ FlowCanvas or Behavior Designer.

    I saw in some videos that there is a nice "Can see" feature in Behavior Designer. Is there something like that in NodeCanvas, too?

    And I saw Behavior Designer gots a lot of 3rd Parti-Support. How can I handle that with Node-/FlowCanvas without "real" coding? Would I use FlowCanvas to visually code / connect to them?

    I think the most in this thread only uses NodeCanvas, but maybe some people could tell me why I should prefer NodeCanvas over Behavior Designer?

    I really like the UX of NodeCanvas, but it seems that there are not really tutorials out there. There's a good one at YouTube, but it seems to stop / no new videos (
    ).

    So are there any other tutorials out there?

    Thank you :)
     
    nuverian likes this.
  20. DeepShader

    DeepShader

    Joined:
    May 29, 2009
    Posts:
    682
    Does NodeCanvas supports localization in dialogs?
     
  21. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    94
    So, it only happens when I load into my Game scene. I've done a t:blackboard,fsmowner, and behaviourTreeOwner on the entire scene and there's only 1 result. I tried deleting it from the scene and it still throws the error. Any other ideas to try to locate the culprit? lol

    Also did a t:graph in my Project folder and only got 1 result. Exported it to json and nothing is a match vs "Spine". The only thing I recall using this on is something I long ago deleted from my Game scene.
     
    Last edited: Sep 20, 2017
  22. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    94
    I'll hope for an official response on this one also, but what I did was make variables for all my dialog entries and then you can iterate the graph's variable names and see if there's a key match in your localization dictionary (unsure how you go "get" a key value pair currently but I just have a large Dictionary<string, string> for the current lang). The Dialog tree supports doing things like [blacksmith_1] being typed into Nodes and it will look to the blackboard for that variable and use it to display text. Allows you to change lang at runtime etc by simply re-initializing all dialogs with the new lookups.
     
    nuverian likes this.
  23. Tamino

    Tamino

    Joined:
    Apr 15, 2013
    Posts:
    9
    Did you ever get a chance to implement UnityEvent? I'm not finding support for it in NodeCanvas.
     
  24. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hello,

    Considering I understood your question correctly, the only way to assign a different target actor for each action in an Action List, would be to override the target and (instead of using "Self") assign a different object reference per action, as shown in red rectangle in the image bellow.
    OverrideSelf.png

    Doing this, will make it so that the action is performed by the assigned object (in this case gameobject John) and the action will completely ignore the actor that the node is set to be using, while if the target is left to "Self" which is by default, the actor set for the node, will be used as normal.
    Please let me know if this works for you, or if maybe I misunderstood your question.
    Thanks!


    Hello,

    Thanks for your interest in NodeCanvas and FlowCanvas.

    - Yes, NodeCanvas, among other many tasks, does also include a "Can See" condition, as well as Seek, Wander, Flee and Patrol actions.

    - Regarding 3rd party integration, NodeCanvas already has a lot of them as shown and possible to be downloaded from the website here, but new 3rd party integration requests are always welcome!
    The reason why there are fewer 3rd party integration extensions available than say Behaviour Designer in total, is simply the fact that both NodeCanvas and especially FlowCanvas, are both capable of calling functions, or getting/setting properties of any component type (even from 3rd party assets) without scripting and through reflection, which practically makes creating explicit 3rd party integration packages redundant. Thus 3rd party integrations are preferable made, only when using the reflection system does not suffice, which in most cases it though does :)

    - There are a lot of convenient and advanced features that NodeCanvas has, which most other competitive software do not, but without being nitpicking here, two of the most prominent comparisons that can be made, is the fact that NodeCanvas comes with three different, yet seamlessly working together visual systems (Behaviour Trees, FSMs, Dialogue Trees) included in the same package, as well as the fact that it has already proudly been used by great games and teams as showcased here :)

    - Video tutorials at the moment is indeed an issue due to a language barrier, but there still exists an open job position for that, so hopefully someone will soon apply for the job! With that said though, I am always happy to help through the forums, or direct email contact in any way I can possibly can.

    - Regarding Dialogue system localization, there is no built-in localization support in NodeCanvas, but if you don't mind scripting, you could integrate an existing/other localization system (basically a table/dictionary with the localized versions of dialogue) with NodeCanvas.
    Each dialogue statement in NodeCanvas, has a special "MetaData" (string) parameter in the inspector, which can be used to give that specific dialogue statement an ID. Then with a bit of scripting, you can use the MetaData ID in runtime, to fetch and display the localized version of that dialogue statement in the UI, from an existing table/dictionary that contains the various localized versions. Once again this required some scripting as well as an existing localization system in place, but a lot of people using NodeCanvas have already used this solution to localize the dialogue trees.
    The solution that @TSabos provided above (thanks!) using variables is also a valid one, but I think that using the MetaData parameter to localize the displayed text as described above is probably easier, considering that scripting is though involved.

    If you have any other questions at all, or need any further info on the above, please let me know.
    Thanks again for your interest in NodeCanvas and FlowCanvas!

    Hey,
    Hmm. That's really weird... Is it at all possible for you to please send me the scene in question to "support_AT_paradoxnotion.com" to check what can potentially be wrong there?
    I also forgot to ask you earlier, but are you using the latest version (2.6.3), or a prior version to that?
    Please let me know.
    Thanks!

    Hello,
    Yes, CheckUnityEvent (similar set with CheckCSharpEvent) has been created and will be included in the next version. For your convenience though, I have also attached the unitypackage containing those new conditions relevant to UnityEvents.
    Let me know if these works for you as expected.
    Thanks!
     

    Attached Files:

  25. a-t-hellboy

    a-t-hellboy

    Joined:
    Dec 6, 2013
    Posts:
    180
    Thanks for answering, If you can answer sooner, it can be awesome.

    How can I override agent in my custom task ?

    And how can I use inConnections variable in my task ?
     
    Last edited: Sep 22, 2017
  26. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hey,
    If you want your custom task to have the ability for their target agent to be overridden like in the actions I posted above, you will need to derive from the generic version of ActionTask<T>, rather than simply ActionTask, where T can be any Component type, but preferably the Component type that the action requires to work correctly. If no specific Component type is required, but rather any component, or simply just a gameobject suffice, you can derive from ActionTask<Transform>. For example:
    Code (CSharp):
    1. using NodeCanvas.Framework;
    2. using ParadoxNotion.Design;
    3. using UnityEngine;
    4.  
    5. [Description("Will log the current assigned agent in the console")]
    6. public class Example : ActionTask<Transform> {
    7.  
    8.     protected override void OnExecute(){
    9.         Debug.Log(agent);
    10.         EndAction();
    11.     }
    12. }
    Remember that the property "agent" when used in a task derived by the generic version as above, returns a value which is already of the same type as the generic argument used. Thus in this case, "agent", returns a Transform.

    Doing the above, will make the task show the relevant inspector for allowing you to override the agent if required (by clicking the checkbox next to "Self").
    OveridableAgent.png

    Let me know if that helps, or if you need any further explanations!
    I'd also like to suggest if possible by you, to please use the official forums for support if time is of the essence, since I tent to answer questions posted there first :)

    Thanks!
     
  27. a-t-hellboy

    a-t-hellboy

    Joined:
    Dec 6, 2013
    Posts:
    180
    Thanks for answering.

    Is it possible to use drop down variables of main agent in override agent instead of drag and drop object ? If it isn't I'll make a little change in codes.

    And how can I use inConnections variable in my task ?

    Also I didn't know there is official forums, many thanks for suggestion. I will use it.
     
  28. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    You are very welcome :)
    If you mean using variables from the Dialogue Tree's local blackboard, then yes that is possible in the same way that is done with the other included tasks, by first of course having a variable created and then using the radio button to show the drop-down, after you override the agent using the checkbox, as shown bellow:

    If you mean using the "DialogueActor" variables that the dialogue tree has, similar to how it is done for example in nodes (eg "Instigator"), this is unfortunately currently a limitation and is not possible, but it is something I am looking at supporting in the near future. Let me know if this is what you mean. On the other hand, though, you can of course already create and use variables of type "DialogueActor" in the local blackboard if this is something that you want.

    Regarding your other question about "inConnections", the in and out connections property is not a property of the Task class, but rather of the Node class, and by design, a Task has no access to the Node in which it is assigned to (but of course a Node has to the Task). That means, also by design :), that a Task should be made in such a way as to only care about doing it's own work/functionality. If you want to manipulate connections so that for example alter the flow of the dialogue graph, then you probably would want to create a custom Node, instead of a custom Task, which might be the case if you want to do something that the existing nodes can not.
    May I ask the use case for access to the inConnections property of the node?

    Let me know if that helps, or if I misunderstood any of your questions.
    Thanks!
     
  29. a-t-hellboy

    a-t-hellboy

    Joined:
    Dec 6, 2013
    Posts:
    180
    Actually I want to use "DialogueActor" variables that was defined before. so for now there is no way to use those variables ?

    For inConnections, I've created a custom task like MultiChoiceNode, there are multi input field in dialogue tree flow, I need to know the previous node is StamentNode or not and if it is, show last statement, I think I can use GetParentNodes and do these stuffs.
     
  30. aidinz

    aidinz

    Joined:
    Apr 17, 2016
    Posts:
    63
    Hi,

    As you suggested, instead of making custom states, I'm creating custom ActionTasks for modularity but I'm facing some problems:

    What I'm trying to do is a simple FSM for my most basic enemy that patrols and upon seeing the player, starts to shoot. Please note that I have a custom character controller that uses raycasts to move the enemy rather than applying velocity/force to a rigidbody.

    Most immediate problem is how to variables/methods between different ActionTasks. I think I have to use blackboards but setting one in the blackboard and calling blackboard.GetVariable<float>("SightLength") does not work as a float but NC's own float which can not be casted to a normal float.
     
  31. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hey,
    I have just replied you in your post on the NodeCanvas forums.
    Thanks for using them :)

    Hey,

    Indeed the best way to communicate data between different tasks, would be by using blackboard variables.
    The 'GetVariable<T>(string)' method, indeed returns an object of type 'Variable<T>', not of type T.
    What you want to use instead, is 'GetValue<T>(string)' for getting a variable value and 'SetValue(string, object)' for setting a variable value. That is, if you want to get/set blackboard variable values directly.

    A better alternative to use blackboard variables in your custom ActionTasks though, would rather be to use public fields of type 'BBParameter<T>', which will allow you through the inspector of the ActionTask, to select a blackboard variable from within a dropdown list, similar to how it is done with all ActionTasks that come included with NodeCanvas
    .
    For example:
    Code (CSharp):
    1. using UnityEngine;
    2. using NodeCanvas.Framework;
    3.  
    4. public class BBParameterExample : ActionTask {
    5.  
    6.     public BBParameter<int> number;
    7.  
    8.     protected override void OnExecute(){
    9.         //read the 'number' value through the .value property.
    10.         Debug.Log( number.value );
    11.         //write the 'number' value also through the .value property.
    12.         number.value ++;
    13.         EndAction();
    14.     }
    15. }
    This example action task above, will allow you to either enter an integer value directly, or link the parameter to a blackboard variable of type integer (in this case it is linked to an integer variable named "myInteger").
    BBParameterLink.png

    Let me know if the above work for you.
    Thanks.
     
  32. aidinz

    aidinz

    Joined:
    Apr 17, 2016
    Posts:
    63
    Thanks, that did it. My enemy is patrolling! (Perhaps the only time I'm happy for my "enemy"!)

    One more thing, I need to have a logical OR in one of my action states. In my waiting state, I need to wait for 1 second and then transit to another state but I need to constantly check for another check, which is searching for player, and if that happens I need to transit to shoot state. So these should happen in parallel and whenever one happens first should do the transition.

    Please note that I've included both transitions on my state and the default "Actions Run In Parallel" is selected.

    (I'm sure this is included in the documentation but I'm afraid I can't understand the included pdf file.)
     
  33. aidinz

    aidinz

    Joined:
    Apr 17, 2016
    Posts:
    63
    Another question. I like the AnyState concept, lets me parallelize checks, but is it possible to "resume" getting to a AnyState?

    For example my character is doing something and suddenly saws the player, goes to shoot and chase the player and when all is done I want it to get back to where it was and continue.
     
  34. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087

    Hey,

    Just by having multiple transitions out of a state, will make it so that these transitions are constantly checked (in parallel) and as soon as one is true, the transition will take place. So conditions assigned to transitions can be checked on parallel, but actions on a state work differently. A state that is set for "Actions Run In Parallel", means that all the action will update simultaneously, while if set to "Action Run In Sequence", actions will update one after the other, thus there will be no more than 1 action running at the same time.
    So if for example we have a state with ("Patrol, Log Text") actions, if set the "Run In Parallel", then the text will be logged while the Patrol action is also happening, but if set to "Run In Sequence", then the text will be logged only as soon as the Patrol action is done/finished.

    Regarding your question about AnyState, returning to the previous active state before the AnyState transition happened automatically is not currently possible, but it is one of the feature I am looking at implementing, since it has already been requested a few times before :)

    Please let me know if the above help, or if I misunderstood your question about parallel checks.
    Thanks!
     
  35. Kiupe

    Kiupe

    Joined:
    Feb 1, 2013
    Posts:
    528
    Hello,

    I'm working ona BT a colleague of mine made and I'm a bit lost. Actually it's a BT using sub-tree which are used to control an ennemy NPC behaviors. At some point all the nodes in the current path are showing a little "clock" like waiting before continuing to evaluate the whole BT. I'd like to know if it's possible to interrupt/break that "hold/waiting" moment ?

    I don't know what is exactly happening but what I know is when the ennemy loses its target the BT won't go to the according node because it's not evaluation anymore. Is it possible to "gobally" react to something in the BT and stop what is currently running/evaluating/waiting ?

    Thanks
     
  36. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hey!
    I'm sorry but I missed your post. A "clock" icon basically means that some "leaf" node is actively still running. If you are using custom action tasks, then you should be careful to call "EndAction()" to designate that it has finished when it has.

    Regarding interruption, that is possible using the "Interrupt" decorator node, which takes a ConditionTask, which condition when it returns true, this decorator will interrupt it's connected child node if Running, and return Failure to it's parent node.
    Interruptor.gif

    Another way of utilizing interruptions, is to use the "Dynamic" option that some nodes like Sequencer and Selector have. For more information on how the "Dynamic" option works, please take a look at the Reactive Evaluation Documentation.

    Which of the two are better though, really depends on the design of your behaviour tree. If you would like to post a screenshot, or better yet send it to me to support_AT_paradoxnotion.com, then I would be able help better at deciding which solution to use, or whether something is going wrong just in case.

    Thanks!
     
  37. Sluggy

    Sluggy

    Joined:
    Nov 27, 2012
    Posts:
    989
    Just a heads up - the 'Wander' node causes unity to lock up entirely if the agent in question isn't on a navmesh. I've only had this issue in 2017.2 so far. Pretty easy to fix if you add some extra checks for agent.isOnNavMesh before executing anything. Not sure if this affects the other pathfinding nodes.
     
    RecursiveRuby likes this.
  38. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hey,
    Thanks a lot for the heads up! I think it's more on the Unity side the fact that the editor is crashing, but I will add the checks required for the next version just to be on the safe side :)
    Thanks again!
     
  39. RecursiveRuby

    RecursiveRuby

    Joined:
    Jun 5, 2013
    Posts:
    163
    Is it possible to disable activating the graph window every time we click a object that has a behaviour tree attached? Or if not could we have it as an option added to prefs?
     
  40. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hello,

    There is a "lock" button on the top right of the graph editor window. When "lock" is enabled, the graph editor will not try to refresh to any other graph possibly assigned to a clicked gameobject in the hierarchy.
    Please let me know if that is what you mean.
    Thanks.
     
  41. guybro_thunderboots

    guybro_thunderboots

    Joined:
    Aug 27, 2015
    Posts:
    45
    Great asset!

    It'd be nice if there were some way to automatically position nodes (visually), though. I find I'm spending quite some time experimenting, and having nodes not aligned, etc, makes it a bit hard to quickly scan and see what level I'm working at.
     
  42. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hey,
    Thanks a lot. I am glad you like NodeCanvas!
    Sure, I can take a look at auto-alignments in the next version iteration!
     
    guybro_thunderboots likes this.
  43. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    The new NodeCanvas version 2.7.0, is now live on the Asset Store !

    The changes include:
    • New: Robust Graph Minimap!
    • New: Graph Debug Console Window! Logs Graph related stuff and clicking on the logs, automatically opens up the relevant graph and focuses the relevant node.
    • New: Visual Debugging Animations!
    • New: Generic version of Task(T) are now possible to work with interfaces without using the [AgentType] attribute.
    • New: It is now possible to “upgrade” a normal (T) field type in a Task or Node, to a BBParameter(T) without losing original serialized data.
    • New: GUI option for Colored Headers.
    • New: Node and Variables inspector panels are now re-sizable.
    • New: Node documentation now show on mouse over as a popup.
    • New: Connections are now clickable directly on the curve.
    • New: The Node/Task Browser is now multi-threaded and as such loads up very fast and remains responsive.
    • New: Support for Control Copy/Cut/Paste shortcuts.
    • Fix: A lot of improvement in Editor Performance when zoom out.
    • Fix: Serializing default node colors.

    New Graph Minimap
    Minimap.gif

    New Visual Debugging Animations
    FlowAnimations.gif

    New Graph Debug Console
    Console.png


    Enjoy!
     
  44. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    614
    i wanna create a choose ur own adventure game with the nodecanvas FSM.
    how feasible would it be to create states containing Image,Audio,Choices.
    In between states i may have a SLATE Cutscene as a transition.
     
  45. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    614
    Another question,
    For behavior trees, are there any prebuilt packs available,
    like the Movement Pack for Behavior Designer which adds things like "Patrol", "Wander", "Search".
    or would i have to build those behaviors from scratch with nodecanvas?
     
  46. BigToe

    BigToe

    Joined:
    Nov 1, 2010
    Posts:
    208
    I was curious if anyone has used Node Canvas for overall Game Managers? I usually have a Scene Manager and a Gameplay Manager that are defined by enums and a globally accessible state(C# FSM). I feel like when I define states in a Node Canvas FSM, the states I define should effectively replace the whole concept of using enums.

    But I keep going back to having a global backboard with the current game state defined by an enum for the other classes to reference. This feels redundant and inefficient as I keep changing the global game state BB variable with the FSM. Each time it enters a node, it updates the enum game state which it is in. The transitions are typically triggered based on the game state being different then the current node I am in.

    So if I have a character and he wants to check if the current Game State is equal to "Playing" in the Node Canvas FSM, is the best way to do this by just keeping a well maintained class of static strings that mirror the nodes I have created in the FSM? So if I create a game "Playing" node, then update the static string class for reference later?

    Or is there some way that I am missing that exposes the states in an FSM so they are easily accessed and referenced like using enums for states?
     
  47. Kiupe

    Kiupe

    Joined:
    Feb 1, 2013
    Posts:
    528
    Hi,

    I'm about to work on a project with a lot of dialogs. Those dialogs will have conditions and actions based on game values. Those game values could be used by one ore more dialogs that are not associated to the same "NPC" - So I was wondering if it would make sense to bind all those values in a global blackboard and if it is possible to associate a globale blackboard to a dialog tree ? If NPC are not in the same scene, how could I reference a global blackboard ? Could a blackboard be an asset ?

    Thanks
     
  48. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hey,
    FSM States do not really contain anything else other than action scripts that do something :)
    So they can't really contain Images per-se, but can rather contain actions with some Image references that use those images to display them in the UI, or actions with AudioClip references that play those Audio Clips.

    For a Choose your own adventure style game though, I would probably chose to use the Dialogue Tree system, rather than the FSM system, since it has a "Multiple Choice" node already built-in, that easily prompts a choice to the user to choose from, and then continues the flow according to the choice made.

    But even in Dialogue Trees, the same thing as FSMs apply, in that the nodes do not contain images or audio clips per-se, but rather actions that make use of such assets, and depending on what you want to make, there might, or might not be a relevant built-in action already included.
    You can however use Slate cutscenes to show such images or play such audio clips :)
    Choice+Cutscene.png

    NodeCanvas already includes those actions for free in the core package (Flee, Patrol, Seek, Wander). :)


    Hello,

    Hmm. Considering I understood correctly, you might want to consider using Bound Variables instead.
    For example, you could have an GameState enum and a GameManager static class like this:
    Code (CSharp):
    1. public enum GameState{
    2.     Playing,
    3.     Paused,
    4. }
    5.  
    6. public static class GameManager{
    7.  
    8.     public static GameState gameState;
    9. }
    You can then have Blackboard variables be bound to that static GameState enum field (or property) of GameManager, and have all FSM state transitions take place based on that enum (with CheckEnum or CheckVariable(T) conditions).
    BoundEnumVariable.png

    This way, both your own code as well as all the FSMs can both utilize the same enum, which is probably set somewhere in your own code, and this way, the FSMs are just using what already exists, rather than having to manually keep track of that state in some different internal way, by using a Global Blackboard for example. :)

    Please note, that to be able to see your GameManager and GameState types in the popup when adding a new variable, you will first have to add these types in the Preferred Types Editor window.

    Let me know what you think, or if you have any further questions regarding the above.
    Thanks.


    Hello,

    You could indeed have a Global Blackboard with those values and have all your dialogue trees read from that Global Blackboard, however, Global Blackboards are scene bound and at least at the moment there exist no "Asset Blackboard" (although that is in the works). A Global (scene) Blackboard, can however be set to "DontDestroyOnLoad" in it's inspector and as such persist between the different scenes loaded.

    Another solution similar to my previous reply above, in case that these game values you are referring to, are already values defined in some of your own code, would be to use Bound Variables and avoid using a Global Blackboard completely.

    Thus, say for example you have a GameManager like this:
    Code (CSharp):
    1. public static class GameManager{
    2.     public static string chapterName;
    3.     public static int score;
    4.     public static int lives;
    5. }
    You can create a bound variable for each of those fields in the dialogue tree blackboard and as such utilize these field values directly.
    BoundVariables.png

    Let me know if that that works for you, or if I misunderstood the question.
    Thanks!
     
  49. Kiupe

    Kiupe

    Joined:
    Feb 1, 2013
    Posts:
    528
    Ok, it totally make sense and I thing both suggestion are doable. Thanks a lot.
     
    nuverian likes this.
  50. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087