Search Unity

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

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

  1. Async0x42

    Async0x42

    Joined:
    Mar 3, 2015
    Posts:
    104
  2. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    @nuverian I have another feature request: Would it be possible to add a visible input port at the top of nodes so that it becomes possible to create a connection by clicking and dragging from the child's input port?

    Right now if you're working with a node and you want to connect it to a parent you're forced to leave the node, look for the parent, click the parent's out port and then look for the child again. Instead it would be great to just click on the child's input port and simply drag-and-drop it on the parent.
     
  3. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hey,
    I've realized it's a bug in the custom layermask editor in last version. I've PMed you the fix.

    Thanks.

    Hey,
    Sure, I will take a look at this. Thanks for the headstart! :)

    Hey,
    I will take a look at adding this too later on :)

    Thanks!
     
  4. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    Thanks! I think you might have missed my post on the previous page (related to namespace): :oops: http://forum.unity3d.com/threads/no...es-dialogue-trees.227190/page-23#post-2249536
     
  5. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    You are welcome.
    Regarding the CanvasGroup and namespaces, you can add this directive in case you are also using NodeCanvas.Framework:
    Code (CSharp):
    1. using CanvasGroup = UnityEngine.CanvasGroup;
    ...or if you are using NodeCanvas.Framework only for the Blackboard, you can instead use this directive and remove the using NodeCanvas.Framework completely:
    Code (CSharp):
    1. using Blackboard = NodeCanvas.Framework.Blackboard;
    :)
     
  6. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    Fantastic! Thank you very much for this!!! :)
     
  7. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    @nuverian A quick "bug report" here:

    1) When you place a node over a group's title bar, then release the mouse button and then click on the node again to move it, the group's title bar (under the node) gets selected (and moved) instead of the node.

    2) Attempting to move a node before the zoom has finished resolving causes the node to move in weird, unexpected ways.

    3) In any case it would be great for the zoom to resolve more quickly. Right now it takes a while (when you're working quickly) and you can't do anything until the zoom has finished resolving. Which is a bit tedious when repeated dozens of times. :)


    Update:

    And here is a feature request: Do you think it would be possible to add separator lines to the blackboard? It would make the variables easier to organize in groups and be readable as such.

    Here's a quick mockup of what I mean:

     
    Last edited: Aug 17, 2015
  8. BadFoolPrototype

    BadFoolPrototype

    Joined:
    Sep 7, 2013
    Posts:
    14
    Hey Nuverian,
    I am loving NodeCanvas! It is making my life much easier even when debugging finite state machines :)
    Question: I can't find any documentation about dialogue trees, probably I am just missing the link in your website, can you give me more info about that ?
    Thank you!
     
  9. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    @nuverian In addition to my previous post I have a question related to NodeCanvas and DOTween: is there a way to interrupt a tween node once it's been started? I've tried using an Interrupt node with a specific condition just above the DOTween node but it has no effect.

    If there is no way at the moment then would you please consider adding a feature to interrupt a DOTween action/node once it's started?
     
  10. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Sorry for late replies everyone.
    Im on vacation :)

    1. I will fix this in the next version.

    2 & 3. Indeed moving node before zoom resolves is a bit buggy. I will fix this and make the zoom resolve faster anyways :)

    I think I can add this feature in the blackboard. Will certainly take a look at this soon :)

    Hey. Thanks a lot!
    I will update the dialogue tree docs as soon as I come back (currently on vacation). :)
    Meanwhile let me know if you have any questions at all.

    Thanks!

    Currently the DOTWeen action tasks do not implement any intruption. Sure. I will update the tasks to make this possible in the next version though.

    Cheers!
     
  11. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    Thank you for your reply! Have a great vacation! :)
     
  12. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    94
    Is there a guideline for what properties get exposed in bound variables in the blackboard? Most of my custom classes do but I have an Entity class which defined public MonsterData monsterData which is a ScriptableObject. I need to access properties on the MonsterData for my custom actions and it isn't showing up.

    Edit: Kinda odd but didn't realize I needed to put System.Serializable on a ScriptableObject, that seems to expose it but not any properties to reference. Can you not get nested class properties?
     
    Last edited: Aug 18, 2015
  13. nuverian

    nuverian

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

    Currently, only properties declared in the selected Component type can be bound to the variable. What you could do is to create properties within your Entity class that returns properties (or anything else) of the assigned MonsterData. For example:
    Code (CSharp):
    1. public class Entity : MonoBehaviour{
    2.    
    3.     public MonsterData data;
    4.  
    5.     public string name{
    6.         get {return data.name;}
    7.     }
    8.  
    9.     public float health{
    10.         get {return data.health;}
    11.         set {data.health = value;}
    12.     }
    13.  
    14. }
    Let me know.
    Cheers!
     
  14. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    The new version 2.3.7 is now live on the asset store :)
    (I will update the docs for the new stuff when I get back from vacation)

    Cheers!

    @Seith Thanks!
     
    Seith and Async0x42 like this.
  15. Marble

    Marble

    Joined:
    Aug 29, 2005
    Posts:
    1,268
    Is there a way for me to save Blackboards without using PlayerPrefs?

    I see that Blackboard.Save returns some JSON. I'd like to Load a blackboard using that JSON (i.e. do my own serialization). Is that possible?

    I also wanted to request a way to exclude or include blackboard variables from a load or save, kind of like the "non-editable" feature that exists currently.
     
    Last edited: Aug 19, 2015
  16. nuverian

    nuverian

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

    The current Save/Load, uses PlayerPrefs for storage. I will need to add some extra methods or overrides for that. Here is a rather quick version of something that I can add in the next update. Please add this in Blackboard.cs :
    Code (CSharp):
    1.         public string Serialize(){
    2.             return JSONSerializer.Serialize(typeof(BlackboardSource), _blackboard, false, _objectReferences);
    3.         }
    4.  
    5.         public bool Deserialize(string json){
    6.             try
    7.             {
    8.                 _blackboard = JSONSerializer.Deserialize<BlackboardSource>(json, _objectReferences);
    9.                 if (_blackboard == null) _blackboard = new BlackboardSource();
    10.                 _blackboard.InitializePropertiesBinding(propertiesBindTarget, true);
    11.                 return true;
    12.             }
    13.             catch { return false; }
    14.         }
    Regarding not saving certain variables (eg 'protected' ones) is a very nice suggestion. I can look into adding this in the next version since it requires a bit more than the above. If you are in a hurry, I can take a look at this tomorrow and send you the code changes :)

    Let me know if this works for you.
    Cheers!

    Hello,

    Please make sure to use the last version of both FlowCanvas and NodeCanvas from the asset store to ensure compatibility between the two products.
    After you import both products, simply delete the subfolder named "Framework" under either NodeCanvas or FlowCanvas folder.
    It seems here that you are using a rather old version of NodeCanvas :)

    Let me know.
    Thanks.
     
  17. Marble

    Marble

    Joined:
    Aug 29, 2005
    Posts:
    1,268
    That works great for me, nuverian; I'm not in a rush to get protected blackboard members, but it's nice to know it's on the way. Thanks for considering my suggestions!
     
  18. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    @nuverian Hi, I haven't updated yet but I have a question regarding the upgrade process. I have tweaked some action nodes code and I have added actions of my own. And I know that the preferred upgrade method is to get rid of the previous NC folder before upgrading.

    So my question is: what do you recommend in terms of storing my own actions? Do I have to first do a backup, then upgrade and then manually copy over all the files I have added/modified? Or should I store my custom actions in a different folder that won't be deleted when I upgrade NC? In which case would they remain available in NC?
     
  19. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Thanks for letting me know and you are welcome. It's a nice suggestion :)

    Cheers!


    Hey,

    It's best to keep all your custom tasks, nodes, graphs (anything custom) in a seperate folder, yes.Then remove NodeCanvas folder and import anew.
    Folder structure does not matter, so all your custom tasks will of course be available.

    Project backup is of course always a good thing to do in any case :)

    Regarding tweaking action tasks of the original NC package, that can be a bit problematic, so in cases where you think a tweak is needed, it's super best to either create your own custom task based on the original if need be, or tell me to add some feature which might be missing in the task :)

    Cheers!
     
  20. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    Ah that's what I thought! So I went ahead and moved all my custom actions and conditions into a different folder, thanks! :D

    As far as needing to modify a default action I only had to tweak the color of the text in the DebugLogText action, like so:


    Code (CSharp):
    1.    ////////////////////////////////////////
    2.      ///////////GUI AND EDITOR STUFF/////////
    3.      ////////////////////////////////////////
    4.      
    5.      private Texture2D _tex;
    6.      private Texture2D tex{
    7.        get
    8.        {
    9.          if (_tex == null){
    10.            _tex = new Texture2D(1,1);
    11.            _tex.SetPixel(0, 0, Color.white);
    12.            _tex.Apply();
    13.          }
    14.          return _tex;      
    15.        }
    16.      }
    17.  
    18.      void OnGUI(){
    19.  
    20.        if (Camera.main == null)
    21.          return;
    22.  
    23.        var point = Camera.main.WorldToScreenPoint(agent.position + new Vector3(0, labelYOffset, 0));
    24.        var size = new GUIStyle("label").CalcSize(new GUIContent(log.value));
    25.        var r = new Rect(point.x - size.x /2, Screen.height - point.y, size.x +10, size.y);
    26.        GUI.color = new Color(.2f,.2f,.2f,0.5f);
    27.        GUI.DrawTexture(r, tex);
    28.        GUI.color = new Color(1f, 1f, 1f, 1f);
    29.        r.x += 4;
    30.        GUI.Label(r, log.value);
    31.        GUI.color = Color.white;
    32.      }
    The reason was the text was appearing as light gray on slightly-less-light gray and wasn't too great for readability.
     
  21. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    @nuverian I just met a problematic situation; so far I was working with only one character and everything was fine. I was working on an asset graph and the character was reacting based on the graph. But now I have duplicated the character and the two characters seem to act/react exactly at the same time, rather than individually.

    I thought that maybe if I clicked on Bind Graph (in the Behavior Tree component) then the characters would behave distinctly but that's not the case. They seem to both inherit the same board variables and values.

    Which is of course a huge problem. Do you know how I could make the 2 characters behave differently based on their own particular situations?

    I'm sure I must be missing something obvious here... :(
     
  22. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    @Seith

    I'm not sure I understand whats the problem is exactly here. Can you please clarify a bit what do you mean by 'behaving the same'?

    Thanks.
     
  23. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    Sorry, so here are more details about what I'm doing:

    - I have created a behavior tree as an asset.
    - This behavior tree is assigned to the first character.
    - A blackboard is part of the behavior tree and holds variables like the current state of the character, its target, etc... (and is also attached to the character as a component)
    - Everything works fine.

    But...

    - I then duplicate my character game object, so I now have 2 characters.
    - The second character has the same behavior tree and blackboard attached (as components) as the first character.
    - When I enter play mode, whenever the first character enters a certain state (stored as bools) then the second character enters the same state.

    It's as if they were connected somehow. I thought it was perhaps because they have the same tree/blackboard and I was wondering how to "separate" them.

    But maybe I'm completely misunderstanding how the system is supposed to work...

    Edit:
    Oh my I'm so silly! I think the error is in my code! I'm going to double-check it...
     
    Last edited: Aug 20, 2015
  24. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    @Seith
    The way you are doing this is correct. At runtime, the BehaviourTree asset is instantiated for each BehaviourTreeOwner, and since each BehaviourTreeOwner has it's own blackboard component the agent should respond relevant to it's own Blackboard variables and it's own BehaviourTree instance.

    Please let me know if it's something on your code, otherwise I will have to investigate further.

    Thanks!
     
  25. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    Yep, that was it! I did a silly mistake in my code which led me to believe the two characters were somehow connected. I'm very sorry for the false alarm... :oops:
     
  26. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    No problem of course and thanks for letting me know! :)
    Cheers!
     
  27. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    @nuverian I have another feature request: Could you please change the background grid color to black (or at least a different color) while game mode is on? I've lost count of the number of times I started tweaking the nodes only to realize that game mode was still on and I was going to lose my current work... :rolleyes:
     
    Async0x42 likes this.
  28. nuverian

    nuverian

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

    I can definetely add this in the next version :)
    Thanks!
     
  29. terravires

    terravires

    Joined:
    Mar 27, 2013
    Posts:
    103
    Any chance of having this updated to 5 functions?

    Getting about 10 warnings about obsolete functions in Framework/Design/Editor/Windows/* usually about EditorWindow.title and DOTweenEditor.dll.

    Using 5.2.0f2

    Cheers
     
  30. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    @nuverian Hello, is there a way to save a blackboard as a prefab? I create my characters in the editor via code and I'm looking for a way to assign to them a specific behavior tree, along with the appropriate blackboard (the same for all the same character types)...
     
  31. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Sorry for late replies.

    Hey,
    The warnings about the EditorWindow.title have been fixed in last version. Are you using the latest version from the asset store?
    I will update to the new DOTTween as well. Thanks :)

    Hey,
    At least currently, it is not possible to assign a prefab Blackboard to the GraphOwners, but could be something I can take a look at :)
    Since you are setting this up in the editor, you could instead, create a gameobject with a Blackboard component and the variables you want in it as a prefab and then use EditorUtility.CopySerialized to copy the prefab Blackboard component to each character's Blackboard component.
    So in the above solution, the prefab blackboard acts more like a source for the copy, rather than being actualy used.

    Let me know if that works for you.
    Thanks
     
  32. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    Thank you for the tip, I'll do like that for now! :)
     
  33. Async0x42

    Async0x42

    Joined:
    Mar 3, 2015
    Posts:
    104
    With Unity 5.2 right around the corner, your next version will need a ' || UNITY_5_2', just a headsup! (since I'm getting those messages with 5.2 right now)
     
  34. sanpats

    sanpats

    Joined:
    Aug 24, 2011
    Posts:
    343
    Just found a nasty bug. Changing Start node cause some node to be an invisible shadow. Not happen in every graph, but the graph that do happen, always happen in the same node(s).



     
    Last edited: Aug 27, 2015
  35. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hey,
    Indeed. I will do that. Thanks for the heads up :)
    Cheers!

    Hey,
    Thanks. I will take another closer look that this issue ASAP!
     
  36. sanpats

    sanpats

    Joined:
    Aug 24, 2011
    Posts:
    343
    Hey, How it goes with that bug. :)

    I found another bug. I want to create a Wait For Event action node in BT.
    This code works:
    Code (CSharp):
    1. using NodeCanvas.Framework;
    2. using ParadoxNotion;
    3. using ParadoxNotion.Design;
    4.  
    5. namespace NodeCanvas.Tasks.Actions
    6. {
    7.  
    8.     [Category ("✫ Utility")]
    9.     [EventReceiver ("OnCustomEvent")]
    10.     public class WaitForEvent : ActionTask
    11.     {
    12.         public BBParameter<string> EventName;
    13.  
    14.         protected override string info {
    15.             get { return "Wait For Event [" + EventName.value + "]"; }
    16.         }
    17.  
    18.         public void OnCustomEvent (EventData receivedEvent)
    19.         {
    20.             if (receivedEvent.name == EventName.value) {
    21.                 EndAction (true);
    22.             }
    23.         }
    24.     }
    25. }
    However, if I use the equivalent FlowScript in the same BT:

    [~CUSTOM EVENT (Self) [..some string...]] ----> [Finish (Success:True)]

    I will get the following error:

    The event comes from another graph in a different GameObject that send a global event, then destroy itself in the next state using your built-in Destroy Game Object action.
     
    Last edited: Aug 31, 2015
  37. nuverian

    nuverian

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

    I was off for the weekend. Will take a look at the previous issue in comming days, starting tomorrow :)
    Regarding this new bug, please open up Graph.cs and in method SendGlobalEvent, at about line #421, please change the content to the following:
    Code (CSharp):
    1.         public static void SendGlobalEvent(EventData eventData){
    2.             foreach(var graph in runningGraphs.ToArray())
    3.                 graph.SendEvent(eventData);
    4.         }
    (.ToArray() is added)

    Let me know if you encounter any other issue :)

    Thanks!
     
  38. cavila

    cavila

    Joined:
    Jun 4, 2013
    Posts:
    67
    Are there any plans to integrate uFrame with Node Canvas?

    I'm trying to decide between NC and Behavior Designer.
     
  39. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    Whatever your choice ends up being you can rest assured that both Justin on Behavior Designer and @nuverian on Node CanvasI are doing a fantastic support job; they're reactive and open to suggestions.

    Beyond that it's a matter of taste; I ended up switching to Node Canvas for Ghost of a Tale's AI recently because I'm more of a visual person and being able to visually track everything in real-time is a boon.

    Mind you there is a similar visual feedback with Behavior Designer but I would say maybe it is a little more geared towards coding. But again, choosing between the two you really can't go wrong.
     
    nuverian likes this.
  40. cavila

    cavila

    Joined:
    Jun 4, 2013
    Posts:
    67
    Thank you for your feedback. It does confirm the vibe I get from reading their respective websites.
     
  41. sanpats

    sanpats

    Joined:
    Aug 24, 2011
    Posts:
    343
    @nuverian

    When use EndAction(bool) in the middle of OnExecute(), even the OnStop() is already run. the rest of the OnExecute will still continue to run. Is this as intend? Should I use return; after EndAction to stop the code from continue running?
     
  42. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    @cavila
    Obviously I'm biased over the two products :)
    Regarding UFrame integration, to be honest I don't think it makes much sense in integrating the 2 products, at least in my mind and as such I didnt have a plan for this. What kind of integration are you after?
    Cheers!

    @Seith
    Thanks for the input :)

    @sanpats
    Yes. Calling EndAction doesn't in any way stop the rest of the method execution. You should use "return;" after calling EndAction :)
    Cheers!
     
  43. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    755
    No problem! :)

    By the way I was curious, when do you think we'll get a new version of Node Canvas? I'm especially in need of the "interrupt Tween node" decorator. Plus all the other nice things you integrated since last time of course... ;)
     
  44. cavila

    cavila

    Joined:
    Jun 4, 2013
    Posts:
    67
    uFrame attaches a MonoBehaviour script (called View) to an object in the scene. That view has a reference to a class that inherits from Object (called the ViewModel). When the value of some property on the ViewModel changes the View gets the notification, and can do something about it on the screen.

    So, the ViewModel has the data that actually matters. The way I see it, with my limited knowledge of NodeCanvas, the ViewModel will communicate back and forth to the BehaviourTreeOwner and the blackboard scripts through the View. Because NodeCanvas is designed to communicate with MonoBehaviour scripts attached to the same GameObject right?

    In the end, the only integration, that I can think of, would be a way for NodeCanvas to synchronize with uFrame's ViewModel properties automatically. uFrame relies heavily on UniRx and updating the blackboard values only when something changes would be the best case scenario.

    I hope all that made sense.
     
  45. sanpats

    sanpats

    Joined:
    Aug 24, 2011
    Posts:
    343
    @nuverian Is it possible to have a dynamic graph or a dynamic state that can be change at runtime? For example:

    A -> B-> ??? -> C

    A, B, and C are normal nodes/states in a graph, and ??? being a dynamic node. We can specified what node it will be during runtime. This will reduce a number of redundant graphs that vary only in a few node.
     
  46. nuverian

    nuverian

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

    I will commit the a version probably within the weekend :)
    Cheers!

    Hey,

    Thanks for the info. I'm not very familiar with uframe, but I could take a look at this for sure and see what can be done.
    Cheers!


    Hey,

    What you could do that is similar to what you are after, would be to use Sub-FSM and assign the target FSM to use through a Blackboard Variable. As such, each agent is possible to use another FSM in place of the Sub-FSM. Also changing the FSM variable at runtime will work as expected :)

    Let me know if that works for you, or need more clarification.
    Cheers!
     
    Seith likes this.
  47. cavila

    cavila

    Joined:
    Jun 4, 2013
    Posts:
    67
    Feel free to message me if you need a hand with uFrame, it can be convoluted at times. Searching where something happens in the framework can take hours when you are new.

    I went with NodeCanvas after all and started integrating it into our current project. I really dig the minimalist approach and the visual design, actually; the visuals and documentation is what swung me over. What I didn't expect was how simple it is to create and add my own tasks. Keep it that way, it is awesome! As a developer, NodeCanvas is what I thought I was going to get with PlayMaker. I just wish I had found it sooner.
     
  48. sanpats

    sanpats

    Joined:
    Aug 24, 2011
    Posts:
    343
    That's exactly what I want. Silly me, I haven't noticed that Sub-FSM can be assigned through BB. Thanks!
     
  49. malosal

    malosal

    Joined:
    Jun 22, 2013
    Posts:
    151
    Hello, I just purchased this product relatively recently. The problem is, when I looked at the documentation in the 2 suggested links for pdf files, I just can't seem to get to a place where I can start small, and then gradually workup. For example, is there any documentation, that tells you something like "ok lets start with the player, test if his velocity is >0 which will cause this to happen, or if it is 0 do this". Just an example. As of now, the documentation seems to be worded in a way where it either assumes you know alot, or the sentences are written for very difficult level users. Any advice would be great!
     
  50. dancinLion

    dancinLion

    Joined:
    Jul 16, 2012
    Posts:
    14
    Hey,

    I think I discovered a bug. If you have a look at the attached image, you see the two conditions that check for healthCur. No matter what I did, the one that is checking for healthCur < 100 was never returning true. I think I created that node by duplicating the other one that checks for healthCur == 0, allthough I'm not 100% sure unfortunately. However, one of the last things I did was to set the healthCur == 0 node to healthCur < 100, but the Agent_Die flowscript was still only called when healthCur reached 0. I assume that somehow my adjustments to the values have been lost, and the nodes were still having older values in them but displaying the new value. I now have created both values from scratch and deleted the old ones, now the tree is behaving as I would expect. Tell me if you need more information.

    BugReport.JPG