Search Unity

xNode - A general purpose node editor

Discussion in 'Assets and Asset Store' started by Siccity, Oct 30, 2017.

  1. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    xNode lets you make your own node graph systems in Unity. It is easy to use, and comes without bloat.

    You can use xNode for any kind of node based solution. Dialogue systems, state machines, procgen graphs, you name it.

    Feature highlight
    • Pan/Zoom functionality
    • Connection creation / removal
    • Lightweight in runtime
    • Very little boilerplate code
    • Strong separation of editor and runtime code
    • No runtime reflection (unless you need to edit/build node graphs at runtime. In this case, all reflection is cached.)
    • Does not rely on any 3rd party plugins
    • Add/remove connection ports dynamically through editor code
    • Simple, intuitive API. No need to ever touch core code.
    • Node inspectors copy inspector functionality - works with property drawers and attributes

    31379481-a9c15950-adae-11e7-91c4-387dd020261e.png
    Node example:
    Code (CSharp):
    1.  
    2. public class MathNode : Node {
    3.    // Adding [Input] or [Output] is all you need to do to register a field as a valid port on your node
    4.    [Input] public float a;
    5.    [Input] public float b;
    6.    // The value of an output node field is not used for anything, but could be used for caching output results
    7.    [Output] public float result;
    8.    [Output] public float sum;
    9.  
    10.    // xNode will display this as an editable field - just like the normal inspector would
    11.    public MathType mathType = MathType.Add;
    12.    public enum MathType { Add, Subtract, Multiply, Divide}
    13.  
    14.    // GetValue should be overridden to return a value for any specified output port
    15.    public override object GetValue(NodePort port) {
    16.  
    17.        // Get new a and b values from input connections. Fallback to field values if input is not connected
    18.        float a = GetInputValue<float>("a", this.a);
    19.        float b = GetInputValue<float>("b", this.b);
    20.  
    21.        // After you've gotten your input values, you can perform your calculations and return a value
    22.        if (port.fieldName == "result")
    23.            switch(mathType) {
    24.                case MathType.Add: default: return a + b;
    25.                case MathType.Subtract: return a - b;
    26.                case MathType.Multiply: return a * b;
    27.                case MathType.Divide: return a / b;
    28.            }
    29.        else if (port.fieldName == "sum") return a + b;
    30.        else return 0f;
    31.    }
    32. }
    If you want to discuss or need help using xNode, feel free to do so on this thread, or join us on Discord :cool:
    You can find it on its GitHub page
     
    Last edited: Feb 16, 2019
    MediaGiant, AlejMC, DarthIF and 17 others like this.
  2. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    Sounds great! Bookmarked for any future need. Thanks & GL!
     
    Siccity likes this.
  3. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Example xNode usage. Here I have built a dialogue system. No core modifications.

     
    rakkarage and zyzyx like this.
  4. ADoby

    ADoby

    Joined:
    Dec 10, 2012
    Posts:
    21
    Hey, I was wondering how xNode compares to "Node Editor Framework" from Seneral.

    I am looking for a framework to create a state-machine design tool for app states.

    Visuals are not that important. But it has to work reliable.
     
  5. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    I am not 100% confident in how Node Editor Framework works, but i think the main differences lie in API and editor code.
    xNode keeps a strict separation of runtime and editor which means your editor code is kept out of your runtime builds, and using it will feel very familiar to regular custom inspector scripting. For most nodes you don't even need to touch editor code - the system will automatically serialize and display fields just like in the inspector. NEF editor code, unless wrapped in `#if UNITY_EDITOR` is included in your build.

    API-Wise, xNode is very intuitive and follows typical Unity conventions, so using it will be easy if coming from a Unity background.

    xNode is also very new and simple, whereas NEF has existed for a long time and has a lot of features and contributors.

    There may be too many differences to list, and i do not know NEF well enough to make a proper comparison, but xNode is definitely capable for making a state machine.
     
    Last edited: Nov 11, 2017
  6. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Update: xNode now supports [ContextMenu] attribute. Add custom context menus to nodes and node graphs.
    upload_2017-11-20_9-5-12.png
     
    Alverik, rakkarage and zyzyx like this.
  7. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Update:
    • Added global xNode preferences - Modify grid and type colors
    • Added NodeGraphEditor support - You can now add node type constraints on a per-graphtype basis.
    • Added grid snap - Toggleable in 'preferences'

      2017-11-28_10-18-52.gif
     
    Alverik, zyzyx and A-Zhdanov like this.
  8. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    This looks nice... Gonna have a play soon! Thanks
     
    Siccity likes this.
  9. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
  10. allinlabs

    allinlabs

    Joined:
    Dec 31, 2012
    Posts:
    15
    Hi, I'm getting a lot of errors on Unity 2017.2.0p3. Any idea why? I tried the AssetStore version and the github version (master branch).

    2017-11-30_16h33_22.png
     
  11. starikcetin

    starikcetin

    Joined:
    Dec 7, 2017
    Posts:
    340
    This looks beautiful.
     
    Last edited: Dec 20, 2017
  12. lloydsummers

    lloydsummers

    Joined:
    May 17, 2013
    Posts:
    359
    This looks awesome, thanks for sharing it
     
  13. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    It seems like you already have a global class named Node. XNode became confused and used your global class instead. This is something I did not foresee and I have now strictly defined namespaces across all scripts. Try the newest Github version. Should work. Thank you for pointing it out! :]
     
    viesc123, one_one and allinlabs like this.
  14. allinlabs

    allinlabs

    Joined:
    Dec 31, 2012
    Posts:
    15
    Will give it a try after this weekend! Thanks!
     
    Siccity likes this.
  15. EllioBonnet

    EllioBonnet

    Joined:
    Jun 30, 2017
    Posts:
    2
    Thank you for sharing such a great project! I like it so much!

    Could you please show us more examples?
    I am personally interested in examples on:
    1) graph with delayed execution (one node executed, wait for some time, next node executed)
    2) connection between NodeGraph and MonoBehaviour (do we need to use NodeCache?).

    My feature request: could you please include ExposedInput functionality (like in Graphmesh) into the core of xNode?
     
  16. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    I'm glad you like it :)

    I try to develop as many examples as I can, but time has been a little tight lately. Also I'm working on a serializable function class that could benefit xNode state machines and dialogue systems big time.

    1) The way I do node execution is create a new base class deriving from Node having a virtual Trigger() method. From the starting node, simply loop through and call Trigger() on all output connections. You can impose a delay by triggering the next node in a coroutine with a WaitForSeconds preceeding it.
    Code (CSharp):
    1. IEnumerator TriggerNextNodes(NodePort outputPort, float delay) {
    2.     yield return new WaitForSeconds(delay);
    3.     for (int i = 0; i < outputPort.ConnectionCount; i++) {
    4.         TriggerableNode nextNode = port.GetConnection(i).node;
    5.         if (nextNode != null) nextNode.Trigger();
    6.     }
    7. }
    2) Not sure exactly what you mean. Your node graph cannot have direct references to your scene, as it is a project asset, but your scene can reference a NodeGraph simply by adding a public field for it. You shouldn't have to tamper with NodeCache in any case.

    As for ExposedInput, I don't feel it's good enough yet. It is very complex and not very userfriendly. I might add it at some point when I feel it's ready.

    Thank you for your feedback! :D
     
  17. VirtualPierogi

    VirtualPierogi

    Joined:
    Sep 3, 2012
    Posts:
    54
    Hello, beautifull asset, im really hoping to work a lot with Your framework, but i cant get it to work somehow
    im getting this error :

    Assets/xNode-master/Scripts/Editor/NodeEditorBase.cs(39,42): error CS0117: `NodeEditorWindow' does not contain a definition for `GetDerivedTypes'

    Edit: it seems that StrumpyShaderEditor was the culprit.

    Im kinda interested in using this framework for visual/classic hybrid scripting.
     
    Last edited: Dec 16, 2017
  18. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Thanks :)
    Errors like these occur when other plugins forget to put their code in namespaces. I have tried preventing it by strongly typing class namespaces in xNode by typing:
    Code (CSharp):
    1. XNodeEditor.NodeEditorWindow.Bla();
    instead of:
    Code (CSharp):
    1. using XNodeEditor;
    2. NodeEditorWindow.Bla();
    I have done so now as well for NodeEditorWindow so if you update you shouldn't be having any issues with your shader editor.
     
  19. dooly123

    dooly123

    Joined:
    Jul 7, 2015
    Posts:
    51
    Works well, Extremely well-done recommended for anyone who wants to get there systems up and running in only a few hours!
     
    Siccity likes this.
  20. EllioBonnet

    EllioBonnet

    Joined:
    Jun 30, 2017
    Posts:
    2
    Siccity, thank you for your quick response!

    Thank you, I will keep my eye on it.

    Oh, I see. I need to be more specific.

    Actually I've already figured out something. I will put it here for other users.

    Problem:
    Make a binary function, calculated using xNode, the results are returned to MonoBehaviour component.

    Solution:

    1) Make an input node
    Code (CSharp):
    1.  
    2. using XNode;
    3.  
    4. namespace MyNodes
    5. {
    6.     [System.Serializable]
    7.     public class InputNode : Node
    8.     {
    9.         public string name;
    10.         [Output] public float input;
    11.  
    12.         public override object GetValue(NodePort port)
    13.         {
    14.             return input;
    15.         }
    16.     }
    17. }
    18.  
    2) Make an output node
    Code (CSharp):
    1.  
    2. using XNode;
    3.  
    4. namespace MyNodes
    5. {
    6.     [System.Serializable]
    7.     public class OutputNode : Node
    8.     {
    9.         [Input] public float result;
    10.     }
    11. }
    12.  
    3) Make a new type of graph for binary functions
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System;
    4. using XNode;
    5. using MyNodes;
    6.  
    7.  
    8. [Serializable, CreateAssetMenu(fileName = "xNodeBinaryFunction", menuName = "Node Graph/xNodeBinaryFunction")]
    9. public class xNodeBinaryFunction : NodeGraph {
    10.     public float calculate(float x, float y)
    11.     {
    12.         // I know this part is inefficient/long/slow, please take it easy, it is just an example
    13.         foreach (var node in nodes)
    14.         {
    15.             if (node is InputNode)
    16.             {
    17.                 var temp = (InputNode) node;
    18.                 if (temp.name == "x") temp.input = x;
    19.                 if (temp.name == "y") temp.input = y;
    20.             }
    21.         }
    22.  
    23.         foreach (var node in nodes)
    24.         {
    25.             if (node is OutputNode)
    26.             {
    27.                 var temp = (OutputNode) node;
    28.                 return temp.GetInputValue("result", fallback: 0f);
    29.             }
    30.         }
    31.         return 0;
    32.     }
    33. }
    34.  
    4) Create an "xNodeBinaryFunction" graph (scriptable object) with two input nodes "x" and "y", and an output node
    xNode.png

    5) Create a component, which uses this graph
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class myComponent : MonoBehaviour
    5. {
    6.     public xNodeBinaryFunction function; // don't forget to attach your graph here
    7.  
    8.     void Start ()
    9.     {
    10.         print(function.calculate(2, 3));
    11.     }
    12. }
    13.  
    Siccity, do you think this example can be simplified?
     
  21. dooly123

    dooly123

    Joined:
    Jul 7, 2015
    Posts:
    51
    awesome work will definitely try!
     
  22. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    That is one of the methods i use as well. It really depends on your use case which way is best.
    Another way to do it is create a ScriptableObject type which does nothing else than hold a value. you can then reference that same value container both from the scene and the node editor.
     
  23. Ash-Blue

    Ash-Blue

    Joined:
    Aug 18, 2013
    Posts:
    102
    Just wanted to chime in and say thanks for making this ^_^ Was thinking about writing something similar from scratch, but this is a great boiler plate to work off of.
     
  24. Tazadar66

    Tazadar66

    Joined:
    Aug 27, 2013
    Posts:
    57
    Hello !

    Is it possible to make Editor Window with this graph framework ?

    Also is it possible to make a custom file format for the output ?

    Thank you :)
     
  25. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Currently xNode does not support modifying the Editor Window apart from various color and skin settings, but this is on the roadmap.
    Graphs are saved as .asset files because it's a format Unity can read and understand natively. I don't know of a reason to support anything else.
     
    zyzyx likes this.
  26. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    1,193
    @Siccity Is it possible to add support for moving the view position using the middle mouse button like in the animator window. It can be awkward to manage large graphs while being limited to the center even with the zoom feature. I have only been playing with it for a short while but I am liking the workflow. Keep up the good work!
     
  27. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    You can drag the view with right-click :D
    But you're right, the button should be middle mouse. I'll change it next update, hopefully old users won't mind.
    Thanks for your feedback!
     
    zyzyx likes this.
  28. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    1,193
    Ahh silly me. I just assumed that the right mouse button was reserved for context menus. I never tried dragging it.
     
  29. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Here's an overview of the xNode interface. Some might find it helpful :)
    xnodejargon.png
     
    NoSleepTilBrooklyn likes this.
  30. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Asset store update :D
    xNode has been updated to version: 1.2

    This includes:
    • Compatability patches. Now works with Unity 5.3 and 5.4
    • Strongly typed namespaces across the project. Minimizes potential import errors
    • NodeGraph.Copy(). Performs a deep copy of the NodeGraph object
    • Added ability to limit a NodePort to a single connection
    Due to popular request I have also added a 10$ price tag on it. This is entirely optional though, and will serve as donations to show your support of the project. xNode is and will always be free on its GitHub page.
     
    zyzyx likes this.
  31. Icepick

    Icepick

    Joined:
    Apr 23, 2014
    Posts:
    4
    This is really good. Could you share the code for the dialogue system editor you posted a screenshot of? Would be useful to have an example of a more complicated setup for those of us not too familiar with setting up inspectors.
     
    Siccity likes this.
  32. starikcetin

    starikcetin

    Joined:
    Dec 7, 2017
    Posts:
    340
    https://github.com/Siccity/Dialogue
     
    Siccity likes this.
  33. Icepick

    Icepick

    Joined:
    Apr 23, 2014
    Posts:
    4
    Siccity likes this.
  34. starikcetin

    starikcetin

    Joined:
    Dec 7, 2017
    Posts:
    340
    You are welcome.
     
    Siccity likes this.
  35. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Update!
    Just added box selection and more color options!
    2018-01-24_12-24-11.gif
    2018-01-25_10-40-26.gif
     
    starikcetin and zyzyx like this.
  36. toto007

    toto007

    Joined:
    Jul 18, 2014
    Posts:
    33
    Hi guys, I need to create a visual graphic editor that you can edit a Runtime. This graph consists of custom nodes. It is very important that the visual editor graph can work at run time even if it has limited functionality. I found this solution: Https://github.com/seneral/Node_Editor_Framework
    but I want a more solid solution. I want to know if xnode can run in runtime mode and if it allows the user to edit a runtime the graph.
     
  37. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    In xNode the editor itself is editor-only. I haven't seen anyone attempt this, but the API is available for runtime interaction, so it is indeed possible. You'll have to create your own runtime implementation of the editor, using any GUI system. `Node` class contains most of the things you need (position, ports, connections).
     
  38. starikcetin

    starikcetin

    Joined:
    Dec 7, 2017
    Posts:
    340
    Up. This deserves to be seen more.
     
    Siccity and Seneral like this.
  39. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Hi - I think my framework you linked is the only ready solution for that currently, since it's rarely needed.
    Develop branch is pretty solid (and better supported than master), and although it is large due to flexibility and not especially lightweight, if you need a runtime editor, that's kind of inevitable:/
    For editor only, depending on what features you need, xNode is definitely more clean and lightweight:)
     
  40. AW30

    AW30

    Joined:
    Feb 27, 2018
    Posts:
    2
    Hello. I'm fairly new with using Unity and programming as whole, so I've been having some trouble trying to work with this extension.

    I'm trying to use the Dialogue version of XNode that you've made in your GitHub, but I'm not sure how to advance the current Chat node to the next one after choosing an answer.

    Thanks in advance!
     
  41. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Bear in mind Dialogue is a fairly experimental project.
    To answer a question, call `dialogueGraph.AnswerQuestion(int answer);`
    dialogueGraph.current is then updated.
     
  42. AW30

    AW30

    Joined:
    Feb 27, 2018
    Posts:
    2
    Thanks! I'm just trying out a lot of things and a friend reccomended this to me. I'm just using the dialogue version of XNode to get a better understanding of XNode itself.
     
    Siccity likes this.
  43. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Asset store update :D
    xNode has been updated to version: 1.3

    This includes:
    • Added multinode selection
    • Added F for "Home" hotkey
    • Added Ctrl for grid snap
    • Added more color settings
    • Added C# script templates
    • Improved tooltip info
    • Various bugfixes
    As always, the asset store has a 10$ price tag. But xNode is available for free on GitHub.
     
    Novack, mons00n, zyzyx and 1 other person like this.
  44. _MGB_

    _MGB_

    Joined:
    Apr 24, 2010
    Posts:
    74
    Hey,

    Having a few problems trying to use this... I can create a new graph asset and put my derived nodes in it -- all fine.

    When I start up Unity though, my derived nodes aren't visible in the graph assets I've created. The example nodes (math/vector etc) are always visible and work fine!
    If I enter and exit play mode my derived nodes magically appear and all is fine again.

    Not sure what's happening here... maybe a serialisation problem?!

    Ed: xNode v1.3 rel, Unity v2017.3.0f3
    No errors in editor except for an intermittent: Null ref in InspectorWindow.OnSelectionChange.
    Also: when my graph selected in editor the inspector shows the nodes array as all empty, whereas in the example graph they are all set to valid nodes.
     
    Last edited: Mar 26, 2018
  45. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Hmm I can't recreate your issues. Maybe you can send me a .zip with your project so I can look at it?
     
  46. _MGB_

    _MGB_

    Joined:
    Apr 24, 2010
    Posts:
    74
    Pfft! I started it up today to create a repeatable project and it's working fine..?!
    I dunno... will keep an eye on it, thanks for the offer of help.

    Edit: Busted again! will try and isolate it :-/
     
    Last edited: Mar 28, 2018
    Siccity likes this.
  47. ALI3D69

    ALI3D69

    Joined:
    Apr 20, 2014
    Posts:
    19
    is there any video tutorial?
    i cant understand how to use it!
     
  48. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
  49. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    New feature! Now you can organize your connections easier by placing reroute points!
    Simply right-click while dragging a connection to place one!

    2018-04-01_21-38-05.gif
     
    Cor1979, BTStone, Noisecrime and 5 others like this.
  50. orb

    orb

    Joined:
    Nov 24, 2010
    Posts:
    3,037
    I had a go at trying to do something with this thing. It's a nice core, but I ran into an issue for my use-case, a skill system.

    I want to make optional inputs and output, which it looked like the AddInstanceInput()/AddInstanceOutput() methods should be perfect for. But when I used them in a custom context menu method, the graph didn't update. The objects got all the fields, according to the inspector though. So clearly it's just a display issue. But they never display even after reopening the graph window, so there's no way to hook up connections for sockets added this way.

    It would also be nice to be able to rename the nodes in the graph without having to make editor code for it. The title is even read-only in the inspector, so there's no quick workaround without digging into the code and modifying xNode.