public class MathNode : Node {
// Adding [Input] or [Output] is all you need to do to register a field as a valid port on your node
[Input] public float a;
[Input] public float b;
// The value of an output node field is not used for anything, but could be used for caching output results
[Output] public float result;
[Output] public float sum;
// xNode will display this as an editable field - just like the normal inspector would
public MathType mathType = MathType.Add;
public enum MathType { Add, Subtract, Multiply, Divide}
// GetValue should be overridden to return a value for any specified output port
public override object GetValue(NodePort port) {
// Get new a and b values from input connections. Fallback to field values if input is not connected
float a = GetInputValue<float>("a", this.a);
float b = GetInputValue<float>("b", this.b);
// After you've gotten your input values, you can perform your calculations and return a value
if (port.fieldName == "result")
switch(mathType) {
case MathType.Add: default: return a + b;
case MathType.Subtract: return a - b;
case MathType.Multiply: return a * b;
case MathType.Divide: return a / b;
}
else if (port.fieldName == "sum") return a + b;
else return 0f;
}
}
If you want to discuss or need help using xNode, feel free to do so on this thread, or join us on Discord
You can find it on its GitHub page
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.
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! :]
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.
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.
IEnumerator TriggerNextNodes(NodePort outputPort, float delay) {
yield return new WaitForSeconds(delay);
for (int i = 0; i < outputPort.ConnectionCount; i++) {
TriggerableNode nextNode = port.GetConnection(i).node;
if (nextNode != null) nextNode.Trigger();
}
}
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.
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:
XNodeEditor.NodeEditorWindow.Bla();
instead of:
using XNodeEditor;
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.
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:
Make an input node
using XNode;
namespace MyNodes
{
[System.Serializable]
public class InputNode : Node
{
public string name;
[Output] public float input;
public override object GetValue(NodePort port)
{
return input;
}
}
}
Make an output node
using XNode;
namespace MyNodes
{
[System.Serializable]
public class OutputNode : Node
{
[Input] public float result;
}
}
Make a new type of graph for binary functions
using UnityEngine;
using System;
using XNode;
using MyNodes;
[Serializable, CreateAssetMenu(fileName = "xNodeBinaryFunction", menuName = "Node Graph/xNodeBinaryFunction")]
public class xNodeBinaryFunction : NodeGraph {
public float calculate(float x, float y)
{
// I know this part is inefficient/long/slow, please take it easy, it is just an example
foreach (var node in nodes)
{
if (node is InputNode)
{
var temp = (InputNode) node;
if (temp.name == "x") temp.input = x;
if (temp.name == "y") temp.input = y;
}
}
foreach (var node in nodes)
{
if (node is OutputNode)
{
var temp = (OutputNode) node;
return temp.GetInputValue("result", fallback: 0f);
}
}
return 0;
}
}
Create an “xNodeBinaryFunction” graph (scriptable object) with two input nodes “x” and “y”, and an output node
Create a component, which uses this graph
using UnityEngine;
public class myComponent : MonoBehaviour
{
public xNodeBinaryFunction function; // don't forget to attach your graph here
void Start ()
{
print(function.calculate(2, 3));
}
}
Siccity, do you think this example can be simplified?