Material graphs
The standard material types cover most of what a project needs. When they do not, you can build a material as a graph instead: connect nodes, and the editor compiles them into a real shader.
Reach for one when you want something a fixed material cannot express — a scrolling texture, a dissolve, a hologram, water, a colour that changes with viewing angle, a flag that ripples.
Every node with its ports: shader node reference — 95 nodes.
The built-in types are not a separate system with a graph bolted on — standard, physical,
toon and the rest are themselves points inside this same space. So a graph material is not a
second-class citizen: it goes through the same path, gets the same lighting, and works on mobile.
How a graph is shaped
A graph runs from inputs, through maths, into outputs.
| Category | What lives there |
|---|---|
| input | UVs, the surface normal, time, position, textures, which instance is drawing |
| const | fixed numbers and colours you type in |
| math | arithmetic and curves on single numbers |
| vector | building, splitting, mixing and transforming vectors and colours |
| light | lighting terms you shape yourself |
| post | nodes that sample the rendered frame — see screen effects |
| output | what the surface actually looks like |
The surface outputs
The output node is where your graph ends, and its inputs are the physical description of the surface:
| Output | Means |
|---|---|
baseColor | the colour of the surface |
metallic | 0 for a dielectric, 1 for bare metal — rarely anything between |
roughness | 0 mirror-smooth, 1 completely matte |
normal | feed your own normal to add surface detail |
emissive | light the surface gives off by itself |
alpha | transparency |
clearcoat · clearcoatRoughness | a lacquer layer over the top |
ior · transmission · thickness | refraction, for glass and liquids |
Anything you leave unconnected keeps its default, and the compiler folds it away — an output you do not use costs nothing.
Working with instances
Two input nodes exist specifically for instanced objects:
instanceId gives you which copy is being drawn, and instanceColor gives you that copy's
tint.
Feed instanceId into a hash and every copy gets its own tint, size or animation phase — from
a single draw call. A field of grass where every blade sways slightly differently costs the
same as a field where they all sway together.
Both read sensible defaults on an ordinary mesh, so a graph using them never breaks by being used somewhere uninstanced.
Screen effects
A graph that samples the rendered frame is not a surface material at all — it is a full-screen effect applied over the whole scene. Colour grading, vignettes, blurs, scanlines.
The engine notices this by itself: use a node that reads the frame and the graph becomes an effect rather than something you put on an object. Several effects on a scene run in the order you give them.
Textures and colour space
A texture node samples an image resource. Colour images are decoded for you so the maths works on real colour values.
A texture that carries numbers rather than colour — a roughness map, a mask, a height map — must be marked as such, or it will be colour-corrected and your values will be subtly wrong. This is the single most common cause of "my roughness map looks nothing like it should".
Scripts have no access to the graph component, so you cannot set a graph parameter from code.
That is less limiting than it sounds, because the two things people want are both covered:
| You want | Do it |
|---|---|
| Something that animates by itself | use the time input inside the graph — pulsing, scrolling, shimmering all belong there |
| Something driven by game state | drive an ordinary material slot instead: a script can write emissiveIntensity, color, opacity, roughness |
So a beacon that pulses forever is a graph reading time; a beacon that brightens when the
player scores is a script writing emissiveIntensity on a standard material.
Practical advice
Start from a preset. Duplicating a standard material as a graph gives you a correct, complete starting point. Building from an empty canvas means re-deriving lighting you did not need to.
Watch what you add. A graph runs for every pixel, every frame. A texture lookup is cheap; a loop is not. If the frame rate drops after an edit, the last node you added is the suspect.
Save it as a resource and every object using it updates at once — which also means one place to fix when the look is wrong.
Next: Particles — fire, smoke, sparks and dust.