Node graph
Wiring up game logic and building an animation blend tree use the same canvas, the same file format and the same runtime. Only the palette of available nodes differs.
The canvas is shared, the nodes are not
Panning, zooming, the grid, box selection and dragging several nodes at once are the same job whatever the nodes represent, so they are written once.
What stays specific to each editor is what its nodes are and how they draw. Building a second editor would have meant a second copy of everything in the first list, which is where two editors start behaving differently for no reason anyone chose.
The dividing line turned out to be clean. Dragging a wire from one connection point to another stayed with the logic editor, because animation state machines join whole states rather than individual inputs. Had the shared canvas kept track of which connection point a drag started from, half of what uses it would have had nothing to put there.
Connection types
Twelve types, each with a colour. The type is read by colour before it is read by label:
| Type | What it carries |
|---|---|
| Exec | The order things happen in |
| Bool | True or false |
| Int | Whole numbers |
| Float | Decimal numbers |
| String | Text |
| Vector | Positions and directions |
| Color | A colour |
| Object | A reference to an object or an asset |
| Struct | A group of values you defined |
| Texture | An image |
| Event | Something that can be triggered |
| Wildcard | Takes the type of whatever you connect |
Order-of-execution connections are triangles. Value connections are circles. Colour alone is never enough, and a graph is the worst place to rely on it, because a red connection and a green one sit inches apart. The shape difference means the distinction does not depend on being able to tell them apart.
Animation state machines
A state machine is built from the same nodes and wires as everything else, so it inherited the canvas, saving, undo and the properties panel without any of them being written again.
Why it is not built from the existing nodes
The obvious way to say "play this animation or that one" with what already existed is a chain of either-or nodes. That does not work, and the reason is worth writing down.
Those nodes calculate both of their inputs before choosing between them. Twenty states means twenty animations sampled every frame, nineteen of which are thrown away.
The fix could not be a new node, because a node's inputs are always calculated before the node itself runs. It had to happen when the graph is compiled: the work for each state is only generated inside the branch that runs when that state is active. The test measures it rather than asserting it. Two states, one animation sampled.
Transitions are nodes too
A transition has a condition and a name, and something with properties needs somewhere to show them. Making it a node means it gets selection and the properties panel from the canvas everything else already uses.
A state can have several ways out
Which no other kind of node allows. Elsewhere, two order-of-execution wires leaving one point have no defined order, so the editor prevents it. But a state's outgoing wires are not "then do this", they are "these are the ways out of here", and they are considered in the order you made them. A state with three ways out is the ordinary case.
Blending between states, and where the timer lives
The graph itself cannot track how far through a blend it is, and it should not. The same graph running on two characters has two blends in progress at once, so the timer belongs to the character rather than to the graph.
So the split is: the compiled graph records which state is current, which one it is coming from, and how long the blend should take. The character owns the clock, and while a blend is running it evaluates both states and mixes the results.
How they are mixed is chosen in the graph rather than decided by the compiler. An empty choice means an instant cut, in which case none of the blending work is generated at all. That is what keeps the underlying mechanism honest: it selects between things without knowing what they are, which is why the tests for it use plain numbers rather than animations.
The cost is visible and bounded: one animation normally, three during a blend, back to one when it finishes.
Errors appear on the node
A required connection left empty puts a red border on the node itself.
An error that only appears in the log requires you to notice a line, read it, and go looking for the node it names. Putting the error where the mistake is removes all three steps.