Skip to content

Quickstart Guide

CoffeeVampir3 edited this page Mar 29, 2021 · 25 revisions

If at any point you're confused about what in tarnation is going on around here, you can reference the more specific documentation here in the wiki.

Graph Blueprints

Create a class that derives from Graph Blueprint

    [CreateAssetMenu]
    public class TestGraphBlueprint : GraphBlueprint
    {
    }

Root Nodes

Every graph needs a Root Node, to give our blueprint a root we must create and register our new root node:

    [RegisterTo(typeof(TestGraphBlueprint))]
    public class RootTester : RuntimeNode, RootNode
    {
    }

You'll also want the root node to have a port so it can connect to something.

Add a port to the root node:

    [RegisterTo(typeof(TestGraphBlueprint))]
    public class RootTester : RuntimeNode, RootNode
    {
        [Out, SerializeField]
        public ValuePort<Any> rootPort = new ValuePort<Any>();
    }

Here we've defined a Value Port in our case this is an Any which means it can connect to any type of port. This is a port: port example Ports are how you define what can connect where and how.

Now you can hop in and check out your first graph, simply create an instance of GraphBlueprint by taking advantage of the Create Asset Menu attribute you gave it. Then, double click on the created blueprint asset and your graph will open with it's root node.. It's that simple to get an editable graph, but you probably want more than a root node and no content.

More About Nodes

Now to add something we can connect to, we'll make another Runtime Node, this time one we can create in the graph:

    [RegisterTo(typeof(TestGraphBlueprint), "My Second Node")]
    public class MySecondNode : RuntimeNode
    {
        //These port options are: "Show Backing Value?", "Port Capacity" and default to false/single if none are selected.
        [In(false, Capacity.Multi), SerializeField]
        public ValuePort<string> stringValue = new ValuePort<string>();
        [Out(true, Capacity.Multi), SerializeField]
        public ValuePort<string> stringValue2 = new ValuePort<string>();
    }

Viola! Now you can head into your graph and right-click anywhere in the world, you'll see in the dropdown menu options a "Create Node", click that and it'll pull up a search menu where you can find your node which you've named "My Second Node". You can give nodes a more detailed path, for example:

    [RegisterTo(typeof(TestGraphBlueprint), "Dialogue Nodes/My Second Node")]

Will create a new category called "Dialogue Nodes" which your "My Second Node" will now belong to.

Now you know how to make nodes and ports! Next, how do you make the graph do something? Lets extend your root node by overriding it's OnEvaluate function:

    [RegisterTo(typeof(TestGraphBlueprint))]
    public class RootTester : RuntimeNode, RootNode
    {
        [Out, SerializeField]
        public ValuePort<Any> rootPort = new ValuePort<Any>();

        protected override RuntimeNode OnEvaluate(int contextId)
        {
            if (!rootPort.IsLinked()) return null;
            return rootPort.FirstNode();
        }
    }

Now when your root node gets evaluated, if it's linked to anything, it'll return the first node it's linked to. Returning null will tell the evaluator to stop running. Similarly, we can extend our "My Second Node" with some functionality as well:

    [RegisterTo(typeof(TestGraphBlueprint), "Wow/Node")]
    public class MySecondNode : RuntimeNode
    {
        [In(false, Capacity.Multi), SerializeField]
        public ValuePort<string> stringInput = new ValuePort<string>();
        [Out(true, Capacity.Multi), SerializeField]
        public ValuePort<string> stringOutput = new ValuePort<string>();

        protected override RuntimeNode OnEvaluate(int contextId)
        {
            foreach (var link in stringInput.Links)
            {
                if (stringInput.TryGetValue(link , out var value))
                {
                    Debug.Log("Value of link: " + value);
                }
            }

            if (!stringOutput.IsLinked()) return null;
            var index = (Random.Range(0, stringOutput.Links.Count));
            return stringOutput.Links[index].Node;
        }
    }

This will output the value of everything connected to the stringInput ports as long as it's a string. It will also randomly pick any connected port to traverse to next if there's any connections.

Running a Graph:

To execute a graph, you use the GraphEvaluator class:

    public class GraphTester : MonoBehaviour
    {
        public GraphEvaluator evaluator;

        private void Start()
        {
            evaluator.Initialize();
        }

        private float lastTime = 0f;
        private void Update()
        {
            if ((Time.unscaledTime - lastTime < 2.00f)) return;
            evaluator.Step();
            lastTime = Time.unscaledTime;
        }
    }

Make sure to drag your GraphBlueprint into the executor, this will make the evaluator try to evaluate one step of your graph every two seconds. Give it a try!