Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

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

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

  1. BigToe

    BigToe

    Joined:
    Nov 1, 2010
    Posts:
    183
    I am having the crashing problem when creating a new nested FSM or BT within a bound FSM. This occurs with Unity 2017.3.0f3. It does not occur with 2017.2.0p3.
    1) Create a Bound FSM
    2) Create a nested FSM
    3) Click Add New
    4) Name and save file
    Unity Crashes for me every time.
     
  2. BigToe

    BigToe

    Joined:
    Nov 1, 2010
    Posts:
    183
    2017.3.0p4 seems to clear this issue up.
     
    nuverian likes this.
  3. nuverian

    nuverian

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

    This has been brought up another time before, which seems to be some Unity bug indeed :)
    Thanks for letting me know it's resolved in 2017.3.0p4.
     
  4. Adrian_LM

    Adrian_LM

    Joined:
    Aug 1, 2017
    Posts:
    5
    Hi, how can I get the tag of each action task by code?
     
  5. BigToe

    BigToe

    Joined:
    Nov 1, 2010
    Posts:
    183
    I don't seem to be able to check a static function as a script control behavior. I have a static bool function which I can assign to an action stash the return value, then check it...But for some reason I can't use that static function as a check. Am I missing it somewhere?
     
  6. Ladace

    Ladace

    Joined:
    Dec 7, 2014
    Posts:
    35
    Bug report:
    Create two classes derived from MonoBehaviour: ClassA, ClassB
    Attach ClassA and ClassB to a GameObject.
    Use action Set Property. For example, choose ClassB, select a common property in both classes like "enabled", set to false.
    Save.
    Reload the scene.
    Check the action, the class becomes to "Behaviour" rather than ClassB. And the in-game behavior is to set "enabled" of the first "Behaviour" component on that GameObject, could be ClassA component.

    To summary, setting a class's inherited properties will automatically be changed to setting its parent's properties. And this will result in wrong be behaviors when multiple classes with same parents are attached to one GameObject.

    This bug has been there for a while, and is still in the newest version. Please fix it.
     
  7. nuverian

    nuverian

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

    Sorry for the late reply, but I've missed your post completely (please use the NC forums if possible :) ).
    Tasks don't really have tags, rather only Nodes (on which tasks can be assigned of course) do.
    You can iterate all the nodes of the graph and get their tags if you want to, by doing something like this for example:
    Code (CSharp):
    1. public class Example : MonoBehaviour{
    2.  
    3.     void Do(){
    4.         var owner = GetComponent<BehaviourTreeOwner>();
    5.         var graph = owner.graph;
    6.         for (var i = 0; i < graph.allNodes.Count; i++){
    7.             var node = graph.allNodes[i];
    8.             var tag = node.tag;
    9.             //do something with the tag...
    10.         }
    11.     }
    12. }
    Let me know if that works for you.
    Thanks.

    Hello,

    I am overhauling the "Script Control" tasks for the next version to be more straightforward (and fewer). Unfortunately the CheckStaticFunction was omitted. If you don't want to wait for the next version I can send you over a CheckStaticFunction solution for you. If so, just please send me an email to support_AT_paradoxnotion.com.

    Thank you!

    Hello,

    Thanks for the report. This has allready been fixed for the next version. It is actually quite easy to fix if you want to now. Just open up SerializedMethodInfo.cs file and change line #29 to be like this:
    Code (CSharp):
    1. _baseInfo = string.Format("{0}|{1}|{2}", _method.RTReflectedType().FullName, _method.Name, _method.ReturnType.FullName);
    Thanks.
     
  8. Filipinjo

    Filipinjo

    Joined:
    Jan 7, 2014
    Posts:
    22
    If I have interrupt above "Move In Direction Action" it is showing that it's executing it... But the thing is that rigidbody is not moving... If I have an action "Move In Direction Action" attached directly to sequencer, it's working as it should...
    What could I be doing wrong? Any clues?
     

    Attached Files:

  9. Ladace

    Ladace

    Joined:
    Dec 7, 2014
    Posts:
    35
    Thank you @nuverian for maintaining this great tool!

    Also, when I upgraded Unity to a newer version, it always throw a lot of errors from Nodecanvas when building my project. All the errors are NullPointerException from line 255 of UserTypePrefs.cs (line 6 in the code below). Is it a bug? Hope this to be fixed!

    Code (CSharp):
    1.         public static Texture GetTypeIcon(Type type, bool fallbackToDefault = true){
    2.             if (type == null){ return null; }
    3.          
    4.             Texture texture = null;
    5.             if (typeIcons.TryGetValue(type.FullName, out texture)){
    6.                 if (texture.name != DEFAULT_TYPE_ICON_NAME || fallbackToDefault){
    7.                     return EditorGUIUtility.isProSkin? texture : null;
    8.                 }
    9.                 return null;
    10.             }
    The exception is thrown because Unity calls OnValidate function on everything during building. My theory is that it unloads all the resources in folders under Editor during building. So what you get from typeIcons dictionary could be null, and the exception throws.

    Please take a look at this and fix it! Thanks!
     
  10. Censureret

    Censureret

    Joined:
    Jan 3, 2017
    Posts:
    290
    This might be a very simple question. But I am building an RTS type game where there easily could be 1000+ agents in the scene. I was wondering if Nodecanvas has any performance impact that would limit this? or if there is something I should be aware of.
     
  11. Jingle-Fett

    Jingle-Fett

    Joined:
    Oct 18, 2009
    Posts:
    566
    @nuverian I saw it mentioned in an old changelog that we can use OnAnimatorMove in action tasks. I haven't been able to figure out how to do it though, could you point me in the right direction?
     
  12. nuverian

    nuverian

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

    Hmm. There should be no reason for the action to NOT execute if it's show as executing. I don't think that Interrupt Decorator is a problem here. Have you tried using another condition in the Interrupt or another action bellow it just to confirm?

    Let me know.
    Thank you.


    Hello,

    Thanks a lot for your positive feedback as well as for the report :)
    To quickly fix this, please add a null check like bellow. I will take a closer look at this though.
    Code (CSharp):
    1.             if (typeIcons.TryGetValue(type.FullName, out texture)){
    2.                 if (texture != null){
    3.                     if (texture.name != DEFAULT_TYPE_ICON_NAME || fallbackToDefault){
    4.                         return texture;
    5.                     }
    6.                 }
    7.                 return null;
    8.             }

    Thanks!

    Hello,
    NodeCanvas is very optimized and fast after the initialization takes place, but of course the more agents running and depending on what they and their graphs do, naturally, the more performance impact there will be as in everything.
    One thing that you should be aware of, is that initialization, which takes place once for each agent and due to deserializing the graph from json, will have an impact due to allocations because of that json deserialization. So if you for example plan to instantiate 1000 agents in one frame, well, that would certainly have a performance impact in that frame and should generally be avoided by pre-loading the agents.
    But once the agents are initialized, the performance should be solid.

    If you have any other questions, or need any further details, just let me know.
    Thanks.

    Hey,
    Yes that is possible.
    Simply add [EventReceiver("OnAnimatorMove")] attribute in your task and create a method by that same name. Here is an example:

    Code (CSharp):
    1.     [EventReceiver("OnAnimatorMove")]
    2.     public class AnimatorMoveExample : ActionTask{
    3.  
    4.         void OnAnimatorMove(){
    5.             Debug.Log("Animator Moves");
    6.         }
    7.     }
    Let me know if that works for you.
    Thanks.
     
  13. Jingle-Fett

    Jingle-Fett

    Joined:
    Oct 18, 2009
    Posts:
    566
    Excellent, thanks! Another question, when does OnAnimatorMove get called in an action task? Like, does it get called while the FSM/BT is running or only while the action is executing?
     
  14. Censureret

    Censureret

    Joined:
    Jan 3, 2017
    Posts:
    290
    Hey guys.

    I am really getting into node-canvas i was wondering is there a way to use conditions to do an "if else" like statement. So if the task returns true run this action if it returns false run this other action.

    Thank you in advance
     
  15. Censureret

    Censureret

    Joined:
    Jan 3, 2017
    Posts:
    290
    Never mind i actually made my own. if anyone is interested in it please let me know and il post it. basically what it does is it takes a condition action and then if its true runs the left node if false runs the right node.
     
  16. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,053
    Hey. Glad I could help :)
    The callback is always called, not only when the action is running, so it might be a good idea to check "if this.isRunning" within your ActionTask code if that is something required.
    Thanks!

    Awesome. Glad to know you've customized NC for your needs.
    I would be interested to know your solution by the way :)
    Thanks!
     
    Jingle-Fett likes this.
  17. Censureret

    Censureret

    Joined:
    Jan 3, 2017
    Posts:
    290
    Awesome. Glad to know you've customized NC for your needs.
    I would be interested to know your solution by the way :)
    Thanks![/QUOTE]


    Code (CSharp):
    1.     [Category("Composites")]
    2.     [Description("If else statement runs the if true runs left statement else run right")]
    3.     [Color("bf7fff")]
    4.     public class IfElse : BTComposite, ITaskAssignable<ConditionTask>
    5.     {
    6.         [SerializeField] private ConditionTask _condition;
    7.  
    8.         public Task task
    9.         {
    10.             get { return condition; }
    11.             set { condition = (ConditionTask) value; }
    12.         }
    13.  
    14.  
    15.         private ConditionTask condition
    16.         {
    17.             get { return _condition; }
    18.             set { _condition = value; }
    19.         }
    20.  
    21.         private int lastRunningNodeIndex = 0;
    22.  
    23.  
    24.         public override string name
    25.         {
    26.             get { return base.name.ToUpper(); }
    27.         }
    28.  
    29.         private bool ConditionStatus;
    30.  
    31.         protected override Status OnExecute(Component agent, IBlackboard blackboard)
    32.         {
    33.             ConditionStatus = condition.CheckCondition(agent, blackboard);
    34.  
    35.             if (ConditionStatus)
    36.             {
    37.                 outConnections[0].Execute(agent, blackboard);
    38.                 return outConnections[0].status;
    39.             }
    40.             else
    41.             {
    42.                 if (outConnections[1] != null)
    43.                 {
    44.                     outConnections[1].Execute(agent, blackboard);
    45.                     return outConnections[1].status;
    46.                 }
    47.             }
    48.  
    49.             return Status.Running;
    50.         }
    51.  
    52.         protected override void OnReset()
    53.         {
    54.             lastRunningNodeIndex = 0;
    55.             if (outConnections.Count > 2)
    56.             {
    57.                 Debug.LogError("IFELSE conditions has more than two options");
    58.             }
    59.         }
    60.  
    61.         public override void OnChildDisconnected(int index)
    62.         {
    63.             if (index != 0 && index == lastRunningNodeIndex)
    64.             {
    65.                 lastRunningNodeIndex--;
    66.             }
    67.         }
    68.  
    69.         public override void OnGraphStarted()
    70.         {
    71.             OnReset();
    72.         }
    73.     }
    Basically what this does is that it takes a ConditionTask then evaluates it and if "true" runs the left node and if false runs the right node.

    It is very very useful and can save a lot of time :)
     
    nuverian likes this.
  18. Jingle-Fett

    Jingle-Fett

    Joined:
    Oct 18, 2009
    Posts:
    566
    Good to know, thanks for the help!
     
  19. river2010

    river2010

    Joined:
    Dec 19, 2017
    Posts:
    1
    Hello, I have a question, I created a similar behavior of more than 40 node tree asset, when I dynamic loading role object, CPU time consuming in the Profiler and GC Alloc looks a little terror, I checked the time-consuming function, found to be appear in the Graph. Deserialize, Deserialize the json data is cost so much, how can change the status quo, please
    upload_2018-3-20_19-52-31.png
     
  20. BACALL

    BACALL

    Joined:
    Feb 21, 2017
    Posts:
    22
    Hello!
    For anyone that knows, how would you use this with Spine? Can this be added? I wan't to know before buy.
    Thanks in advance,
    Peter
     
  21. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    102
    I posted a similar question in this thread on NodeCanvas forum here.
     
    nuverian likes this.
  22. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,053

    Code (CSharp):
    1.     [Category("Composites")]
    2.     [Description("If else statement runs the if true runs left statement else run right")]
    3.     [Color("bf7fff")]
    4.     public class IfElse : BTComposite, ITaskAssignable<ConditionTask>
    5.     {
    6.         [SerializeField] private ConditionTask _condition;
    7.  
    8.         public Task task
    9.         {
    10.             get { return condition; }
    11.             set { condition = (ConditionTask) value; }
    12.         }
    13.  
    14.  
    15.         private ConditionTask condition
    16.         {
    17.             get { return _condition; }
    18.             set { _condition = value; }
    19.         }
    20.  
    21.         private int lastRunningNodeIndex = 0;
    22.  
    23.  
    24.         public override string name
    25.         {
    26.             get { return base.name.ToUpper(); }
    27.         }
    28.  
    29.         private bool ConditionStatus;
    30.  
    31.         protected override Status OnExecute(Component agent, IBlackboard blackboard)
    32.         {
    33.             ConditionStatus = condition.CheckCondition(agent, blackboard);
    34.  
    35.             if (ConditionStatus)
    36.             {
    37.                 outConnections[0].Execute(agent, blackboard);
    38.                 return outConnections[0].status;
    39.             }
    40.             else
    41.             {
    42.                 if (outConnections[1] != null)
    43.                 {
    44.                     outConnections[1].Execute(agent, blackboard);
    45.                     return outConnections[1].status;
    46.                 }
    47.             }
    48.  
    49.             return Status.Running;
    50.         }
    51.  
    52.         protected override void OnReset()
    53.         {
    54.             lastRunningNodeIndex = 0;
    55.             if (outConnections.Count > 2)
    56.             {
    57.                 Debug.LogError("IFELSE conditions has more than two options");
    58.             }
    59.         }
    60.  
    61.         public override void OnChildDisconnected(int index)
    62.         {
    63.             if (index != 0 && index == lastRunningNodeIndex)
    64.             {
    65.                 lastRunningNodeIndex--;
    66.             }
    67.         }
    68.  
    69.         public override void OnGraphStarted()
    70.         {
    71.             OnReset();
    72.         }
    73.     }
    Basically what this does is that it takes a ConditionTask then evaluates it and if "true" runs the left node and if false runs the right node.

    It is very very useful and can save a lot of time :)[/QUOTE]

    Hello,

    Thanks for the follow up.
    I think the Binary Selector that is already included in the package does just that though :)
    Have you checked Binary Selector out?

    Thanks!

    Hello,

    I have replied to your post in the NodeCanvas forums. Please let me know there.
    Thank you.

    Hello Peter,
    There is nothing stopping you from using Spine or any other asset along with NodeCanvas, but there is not any pre-made integration tasks available right now. Thus you will need to create custom tasks (actions/conditions) for that, which is actually quite easy. A very simple example would be something like this:
    Code (CSharp):
    1. using NodeCanvas.Framework;
    2.  
    3. namespace NodeCanvas.Tasks.Actions
    4. {
    5.     public class PlaySpineAnimation : ActionTask<SkeletonAnimation>
    6.     {
    7.         public BBParameter<string> animationName;
    8.  
    9.         protected override void OnExecute(){
    10.             var targetAnimation = animationName.value;
    11.             if (agent.AnimationName != targetAnimation){
    12.                 agent.AnimationName = targetAnimation;
    13.             }
    14.             EndAction();
    15.         }
    16.     }
    17. }

    Let me know if you have any further questions or need any clarification on the above.
    Thank you.
     
  23. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,053
    In case anyone has missed it, the new version of NodeCanvas v.2.8, has recently gone live on the Asset Store.
    The changes of the new version include the following:
    • New: Major editor code refactoring and stepping stones for future development.
    • New: Ability for multiple Attribute Drawers to work together (Compound Drawers).
    • New: Much better search matching algorithm within Menu Browser.
    • New: Script Control Tasks unified to work with both instance and static functions/properties respectively.
    • Mod: GraphOwner prefabs no longer create a Graph sub-asset.
    • Fix: Graph Editor is no longer auto focused when changing Graph Owner selection.
    • Fix: Panning nodes when zoom out.
    • Fix: Several other micro bugs.
    Cheers!
     
    hopeful likes this.
  24. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,053
    Earlier within March, Ghost of a Tale which is proudly utilizing NodeCanvas, had been fully released out of Early Access on Steam. A fantastic game which I urge everyone to check out!

     
    ZGoodwin and hopeful like this.
  25. mcurtiss

    mcurtiss

    Joined:
    Nov 29, 2012
    Posts:
    26
    I'm having an issue implementing manual tick.

    It seems if I have the following snippet from the docs, the following implementation executes the behaviour tree each frame via BehaviourTree:OnGraphUpdate(), even though I've never called StartBehaviourTree() or Tick().


    Code (CSharp):
    1. void Start(){
    2.         for (int i = 0; i < count; i++){
    3.             var agent = new GameObject("Agent").AddComponent<BehaviourTreeOwner>();
    4.             agent.blackboard = blackboard;
    5.             agent.behaviour = bt;
    6.             agents.Add(agent);
    7.         }
    8.     }
    The BehaviourTree is a single SimpleAction node (from the docs, just a Debug.Log statement), and it's OnExecute() is being called each frame.

    When I manually call behaviourTreeOwner.Tick(), the tree gets executed again by BehaviourTreeOwner:Tick().

    No matter what I've tried (and I haven't tried much, I'm new to this library), I can't get the Tick() from OnGraphUpdate() to not execute my btree.

    I see that in the API docs, OnGraphUpdate() is called every frame if the graph is running. Why is it actually executing the debug node, though?

    The functionality I'm expecting is that my BTree - just a single action node - will output its Debug.Log statement only when I call .Tick() via my script.

    EDIT: im a silly goose - the graph was set to repeat.
     
    Last edited: Mar 30, 2018
  26. BACALL

    BACALL

    Joined:
    Feb 21, 2017
    Posts:
    22
    Thank you for the quick reply! That doesn’t tell me very much as I am still learning code. Do you mind ”//” commenting each row? It would help me a lot!
    I don’t really see where spines ”SetAnimation” would go, or another thing how would you then access the new ”Acton” script in NodeCanvas? Can you call methods/functions in scripts from NodeCanvas?
     
  27. Nadan

    Nadan

    Joined:
    Jan 20, 2013
    Posts:
    341
    I'm trying to start Dialogue Tree with C#.

    When I try this example from the manual:

    Code (CSharp):
    1. using UnityEngine;
    2. using NodeCanvas.DialogueTrees;
    3.  
    4. public class dialogue : MonoBehaviour {
    5.  
    6.     public DialogueTree dialogue;
    7.  
    8.     void Update(){
    9.         if (Input.GetKeyDown(KeyCode.Space)){
    10.             dialogue.StartDialogue();
    11.         }
    12.     }
    13. }
    I get error: Assets/Misc/Scripts/Example.cs(10,13): error CS1061: Type `NodeCanvas.DialogueTrees.DialogueTree' does not contain a definition for `StartDialogue' and no extension method `StartDialogue' of type `NodeCanvas.DialogueTrees.DialogueTree' could be found. Are you missing an assembly reference?
     
  28. zenGarden

    zenGarden

    Joined:
    Mar 30, 2013
    Posts:
    4,538
    Hi,

    The plugin import makes an error with Unity 2017.3.0f3

    Error CS0066 'UserTypePrefs.onPreferredTypesChanged': event must be of a delegate type

    //Raised when the preferred types list change
    public static event Action onPreferredTypesChanged;


    What can i do ?
     
  29. Censureret

    Censureret

    Joined:
    Jan 3, 2017
    Posts:
    290
    Hello.

    I have been looking at the documentation but without luck (maybe I'm blind if so then I'm sorry).

    Could anyone tell me how it is possible for 1 agent to communicate with another in node-canvas? Is there a built-in message system I can use?

    My use case:

    Agent 1 waits for Agent 2 to be ready to do an animation when Agent 2 is ready he wants to inform Agent 1 so they can do something at the same time.
     
  30. zenGarden

    zenGarden

    Joined:
    Mar 30, 2013
    Posts:
    4,538
    Is support down like many plugins ?

    Perhaps features out of the in UE4 is the really best choice.
     
  31. TeagansDad

    TeagansDad

    Joined:
    Nov 17, 2012
    Posts:
    916
    Did you happen to upgrade over a previous version?

    I've got the current version of NC running in Unity 2017.3.0f3 and I don't get that error. There was some significant refactoring done in the most recent version, so you want to make sure you completely wipe out the old NodeCanvas folder before importing.

    Yes, there is. It's covered in section 8 "Using Graph Events" in the documentation. (Sorry, can't seem to link to individual pages)

    Try using one of the SendEvent<T> actions, with the "Send Global" option checked; this will send the event to all NC graphs in the scene. If you just want one particular Agent to respond, you could use SendEvent<string> and pass "Agent2" as the string value.

    In Agent 2's BT, you'll need to run a CheckEvent<string> and store the string value, then check to see if it equals "Agent2" (I think there's also a CheckEventValue<string> task that streamlines this a bit).

    Keep in mind that CheckEvent only returns "true" for the frame in which the event was received, so you might want to set a boolean variable when the event is received and then actually process it elsewhere in the tree. And of course, you want CheckEvent running under a composite marked Dynamic (or with an Interruptor decorator).
     
    nuverian and Censureret like this.
  32. Censureret

    Censureret

    Joined:
    Jan 3, 2017
    Posts:
    290
    I am really sorry to come with a new problem but this has been on my mind for quite a while it is a fairly specific problem but I will try to give as much detail it out as much as possible:

    So I have a behavior tree asset that looks like this:

    Udklip.PNG

    What this does, in short, is call a script that then decides which behavior tree should be activated.

    Now let's say that my selection algorithm decides that my agent shall take the "Wander" tree:

    Udklip.PNG

    Now once this tree is completed it will switch back to the Decider tree (the first picture)

    Here my algorithm will determine which tree to take. However here is where the bug occurs: If the algorithm selected the same tree that was previously executed the console will say:

    Infinite Loop. Please check for other errors that may have caused this in the log before this. | On Node 'SEQUENCER' | ID '1' | Graph 'Decider'

    This will cause a repeat of the process until my algorithm tells it to go another tree or entirely bug my agent forever.

    The funny thing is it works fine when shifting between the trees even a tree that has been run before can run perfectly fine as long as it wasn't the previous tree that had just been run (meaning that if the same tree has to run twice in a row the above error is displayed).

    Can anyone tell me why this is happening and what I can do to avoid it?
     
  33. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,053
    Sorry for late replies. I was very ill for the past week.

    Also, please use the official forums for better (= faster) support.
    It is impossible to follow support questions in a monolithic thread like this.
    Support replies will always be faster in the official forums.



    I first missed your post and then I got ill. Can't be more late reply than that. Sorry.
    The following ActionTask is all that is need to play a Spine animation. You don't really need 'SetAnimation'. Just setting the '.AnimationName' property is enough.

    Code (CSharp):
    1. using NodeCanvas.Framework;
    2. namespace NodeCanvas.Tasks.Actions
    3. {
    4.     public class PlaySpineAnimation : ActionTask<SkeletonAnimation>
    5.     {
    6.         public BBParameter<string> animationName;
    7.         protected override void OnExecute(){
    8.             var targetAnimation = animationName.value;
    9.             if (agent.AnimationName != targetAnimation){
    10.                 agent.AnimationName = targetAnimation;
    11.             }
    12.             EndAction();
    13.         }
    14.     }
    15. }
    Also, yes, in NodeCanvas, you can call functions or get/set fields and properties of scripts attached to gameobjects or even static types, by the use of the "Script Control" tasks.

    Thank you.

    Hello,
    The API has changed. Please use this code:
    Code (CSharp):
    1. using UnityEngine;
    2. using NodeCanvas.DialogueTrees;
    3. public class Example : MonoBehaviour {
    4.     //this is what changed (the type)
    5.     public DialogueTreeController dialogue;
    6.     void Update(){
    7.         if (Input.GetKeyDown(KeyCode.Space)){
    8.             dialogue.StartDialogue();
    9.         }
    10.     }
    11. }
    Thanks for letting me know. I've also updated the docs.


    Hello,
    No support is not down by any means. (please read the reasons I've stated in bold on the top of my post).
    I am also using NodeCanvas in Unity 2017.3.0f3 and do not get this or any other compile errors. Have you tried a fresh install (delete previous folder -> reimport package anew) like @TeagansDad said?

    Thanks.


    Like @TeagansDad said, you can indeed use Events. Another way to communicate, would be Global Blackboard Variables ("Tools/ParadoxNotion/NodeCanvas/Create/Scene Global Blackboard"), by which both agents, can reference the same variables.

    Thanks.


    You should really opt to use SubTrees, instead of Switching Behaviours like this. (Simply replace the Switch Behaviour nodes with a SubTree node).

    - When you are using Switch Behaviour, the entire root Behaviour Tree of the agent is switched. That means that the new Behaviour Tree you tell it to switch to, is completely replacing your root behaviour (first image). As such, Switch Behaviour should not be used to replicate SubTrees, but rather only in cases where you indeed want to completely change the root Behaviour Tree of the agent.
    - When using SubTrees though, you don't replace your root Behaviour Tree at all and the SubTrees are simply part/extensions of your root Behaviour Tree (which is pretty much what I think you want here).

    Let me know if that works for you.
    Thanks.

    Thank you for all your replies! :)
     
    TeagansDad and zenGarden like this.
  34. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,193
    Hope you are feeling much better now! :)
     
    nuverian likes this.
  35. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,053
    Thanks a lot! I do indeed feel better now, but almost got to hospital. It was not serious, but it was painful.
    Thanks again!
     
    hopeful likes this.
  36. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    92
    Is there a way to disable the default Inspector when clicking on a Node? Per derived node type perhaps? I'm wanting to experiment with Odin but NC has some pretty serious serialization going on. Is this a horrific path to try to go down?
     
  37. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,053
    Hey,
    I am sorry, but I really did not understand your question or what you want to achieve.
    Can you please clarify?

    Thanks.
     
  38. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    92
    The Odin inspector asset on the asset store. It lets you put attributes across your variables and cs files to really customize and even serialize things like inheritance right in the inspector. The drop down in the following gif is using Odin and its ability to create a Dropdown list on a simple public string someString; variable. The top part is showing its ability to store derived types right in a List<T> in the inspector (amazing).

    The way NodeCanvas draws nodes overwrites DrawDefaultInspector and uses its own very unique drawing. What I'm trying to determine is if there was a way to say, inherit DTNode which I do quite often and for "some" of those nodes, override the OnInspectorGUI to not draw custom and let normal unity serialization take over to see if Odin can be used.
     

    Attached Files:

  39. HolyShovel

    HolyShovel

    Joined:
    Jun 19, 2013
    Posts:
    156
    As I know Nodes can't be saved with Unity serialization system. FC and NC use FullSerializer for this. I think that "integrate Odin drawers" to Node drawing system - its impossible, because its drawing not with Unity Editor class.
     
    nuverian likes this.
  40. curiouspers

    curiouspers

    Joined:
    Aug 7, 2014
    Posts:
    15
    Can anyone put me in the right direction on how to set flipX value on SpriteRenderer of child gameobject depending on float variable?
     
  41. Sasharb

    Sasharb

    Joined:
    May 24, 2014
    Posts:
    2
    Hi! I use Behavior trees in a project and they are working just fine on PC, Mac and Android version of the project, but not with iOS. Do I miss some settings or what could be the reason? It's doesn't initialize at all I think.
     
  42. RobWu

    RobWu

    Joined:
    Jan 16, 2018
    Posts:
    65
    Hi,

    We just finished a small product presentation in Unity, and I was curious how the below would be addressed in a visual programming environment like Node Canvas...

    - The demo product has several default state<->out/in animation clips, all set up in the Animator with triggers etc. These animations are to be started with buttons from a drop down menu.

    - The buttons will 'lock up' and change color during a running animation, also again change color after finishing the animation, to see what 'clip' is active. Think green - red - lightgreen.
    - The buttons are, in addition, also able to hide/show parts of the product model, and/or change materials.
    - Every button will have a boolean function, so out/in for animation, hide/show objects and/or swap materials.

    - Every new activated button will check what animation is currently running, objects are hidden or materials are assigned, and revert all that back to the default state/values first before launching the new animation etc. for the newly clicked button.

    As a testcase I would like to see how much (or less) work this would be inside a visual environment like Node Canvas. It would be a nice comparison project, even with the learning of Node Canvas.

    I already looked into some YT videos on NC, but not entirely sure how to address the above.
    Will there be a separate flow on each button, or can I create something on the menu itself that will have all mentioned functionality to fill for each button?
    Or do I set it up on the animated object itself, and link it all back to the buttons?

    cheers for any answers, tips and links!

    Rob
     
  43. HolyShovel

    HolyShovel

    Joined:
    Jun 19, 2013
    Posts:
    156
    Sasharb and nuverian like this.
  44. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    92
    I'm only looking for a way to override or disable the OnClick editor that pops up on each node, not the drawing system when looking at all the nodes themselves.

    public static void ShowAutoEditorGUI() appears to be what is called per node, so all I really want to see is a way to draw unity default inspector and be able to put normal attributes that unity uses etc so that Odin can hijack drawing it. Still no easy way possible?
     
  45. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    92
    Here's hopefully an easier question ;)

    When we're trying to localize and store [] IDs into nodes, is there any way you can think of to easily have the full text in the node so designers and QA can debug, and also so while designing it's easier to know what [some_quest_5] etc means without having to cross ref an excel document for every entry?

    The only thing I can think of would be a separate field for every single node, but that would require changes to the default Say and Option nodes.
     
  46. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,053
    ---

    @HolyShovel Thank you for all your answers and help! :)

    ----

    For getting/setting properties of components, you will have to use the tasks under the "ScriptControl" category. In your case, that would be the "Set Property" action task. Then in the inspector of the action task, please click "Select Property" and navigate to the "SpriteRenderer/Flip X" (considering SpriteRenderer is attached on the same gameobject as the graph is).
    SetProperty.png

    If you want to set the SpriteRenderer attached to some other gameobject (even a child), then you will have to "override the target", by click the checkbox on the right where the inspector above reads "Use Self", and selecting the new target you want to affect, either by a direct assignment, or through a variable (by clicking the radio circle GUI control).
    OverrideAgent.png

    If you have any more questions or need any clarification to the above, please feel free to open a support thread on the Official Support Forums.
    Thank you.

    Hello,

    If your project and what you want to achieve can clearly be separated into states, then you would be able to use a NodeCanvas State Machine system, where each state can have a number of "actions" to affect the state of the game, and where each state can also have a number of transitions to other states based on conditions (like checking button clicks) so that states can change.

    But if on the other hand everything that happens, is "fired off" by UI buttons for example (as far as I understood correctly by your post), then probably FlowCanvas flowScripts, would be a better system to use. In that case, each button press, will be an event node, which fires off a new "flow", where by connecting nodes into that "flow", you can perform conditions checks and actions (among a lot of other things).

    Please let me know if the difference made sense, or if you want me to elaborate on anything further.
    Thank you.

    Hey,

    Just like @HolyShovel stated, drawing the Unity Inspector within the context of NodeCanvas Nodes or Tasks, is simply impossible, because Nodes and Tasks do not use the Unity serialization system (for a lot of reasons), but rather FullSerializer, thus custom inspectors are created and used in NodeCanvas, which for the most part imitate what Unity Inspectors look like (by using Unity's GUI methods).

    If you have a custom class/struct for which you want to display a custom GUI inspector, then you would please need to create a NodeCanvas' CustomObjectDrawer. NodeCanvas ObjectDrawers and AttributeDrawers, work similar to Unity's Drawers, but instead for objects serialized within the NodeCanvas context (nodes/tasks).

    Once again, because NodeCanvas uses a different serialization system than Unity, it is simply impossible for Unity's existing object/attribute drawers to be drawn within NodeCanvas inspector.

    Regarding your last question about localization IDs, can you please provide a bit more information on your setup and how it relates to your initial question and inspector GUI more precisely?

    Thank you.
     
    SugoiDev likes this.
  47. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,053
    Check out Scoundrel, a great looking 2D stealth game with rogue-lite elements currently in development and proudly using NodeCanvas.

     
    HolyShovel likes this.
  48. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    92
    Sorry, unrelated really. This is a workflow issue where it's hard to debug and follow Quests in the editor when replacing each "Say" node with [some_event_1] just as a random example. When my designer goes to read through the text while playing in unity and wants to know what's coming up or designing them and trying to follow the flow it's very cumbersome. The whole quest is just full of [someID]'s everywhere and nothing readable.

    I think I should have made a brand new field called localizationID and in Internal_OnSubtitlesRequestInfo etc retrieved the localization from in there instead of this workflow.

    We already have over 100 quests implemented so lesson learned for the next game I think? lol ;)
     

    Attached Files:

    nuverian likes this.
  49. RobWu

    RobWu

    Joined:
    Jan 16, 2018
    Posts:
    65
    Hi,

    Completetly missed your comment on my question in the thread....
    In this case everything is indeed 'fired' via UI buttons, so FlowCanvas could be a good match for these kind of projects.

    For more elaborate projects I can see NodeCanvas be a more appropiate solution.

    I will have a look at both to see what would be best.

    cheers!

    rob
     
    Last edited: Jun 5, 2018
    nuverian likes this.
  50. Denzil

    Denzil

    Joined:
    Nov 15, 2012
    Posts:
    8
    Hi,

    I have recently bought Node Canvas and am very happy with it, but I do have a question regarding dynamic that I'm hoping you can help me with. Spent a few hours debugging this but I can't figure it out.

    So this is a segment of my behaviour tree:



    Some background info on what I'm trying to achieve here. My start sequencer node is marked dynamic because I want it to be reactive on the first node / condition task. This condition checks my blackboard variable "TrackTarget" to check if its set (not null).

    Next, my selector node checks a bunch of conditions which informs my agent to actually track the target, if any of them are true. I have not marked this dynamic, because my desired behaviour here is that once this selector returns success, it will stay like that and not re-evaluate until the tracking task is done (replaced here by running forever). This is at least what I understood from the docs.

    However, this does not seem to work this way and this selector is always reactively processed. Even though my tracking task (or "running forever" node) is still running here, it is interrupted when all of the tasks under the selector returns false, completely ignoring the fact that the selector is not marked dynamic.

    If I set the start node to also not be dynamic, then everything works fine, except then it also does not react to changes on the very first condition task (the null check one).

    Am I misunderstanding something or is something else going on here?

    EDIT: I thought perhaps dynamic would treat all children under that node in the tree all the way down as dynamic as well. Is this the case? If so, there's another oddity at play here, because this particular tree is a subtree which is under a dynamic node in the "parent" tree. Another thought, it is not something wrong in the parent tree causing this behaviour because this sub tree is the first (leftmost) node under a dynamic sequencer in the root / parent tree.
     
    Last edited: Jun 5, 2018
unityunity