Unity Shader Graph Guide: Create Shaders Without Writing Code

Created: 2026-02-05Last updated: 2026-07-13

Learn how to create shaders in Unity without programming using Shader Graph. Customize materials intuitively with the node-based visual editor.

"I want the water surface to ripple." "I want the enemy to flash white when it takes a hit." Your goal is crystal clear — but everything you find online is HLSL code that reads like an incantation. Shaders may be the field with the biggest gap between what you want to do and the cost of learning it.

What closes that gap is Shader Graph — Unity's official node-based visual shader editor. Just by connecting nodes with wires, you can build glowing materials, rippling water surfaces, even hologram-style effects, without writing a single line of code.

Illustration of Shader Graph: a clay character connects node boxes with cables, and the preview sphere's material transforms

What You'll Learn

  • The building blocks of Shader Graph (Master Stack, Blackboard, properties)
  • Basic workflow from creation to application, with texture and scrolling examples
  • Changing values from scripts and when to use MaterialPropertyBlock
  • Going further with Sub Graphs, Keywords, and Custom Functions
  • Practical: building a shader that flashes white when hit

Sponsored

How It Differs from Traditional Shaders

Challenges of Traditional Shaders

  • Programming knowledge is required
  • Debugging is difficult
  • Trial and error takes time
  • High barrier for non-engineers

Advantages of Shader Graph

  • No programming required - Just connect nodes
  • Visually intuitive - The processing flow is easy to understand at a glance
  • Real-time preview - See the results of your changes instantly
  • Highly reusable - Create shared parts with Sub Graphs
  • Supports URP and HDRP - Built-in RP support varies by version

Built-in RP support:

Unity VersionBuilt-in RP Support
2021.1 and earlierNot supported
2021.2 and later (Shader Graph 12+)Built-In target supports both Lit and Unlit

On the Built-In target, some nodes and settings that land first in the URP/HDRP targets aren't available. If behavior seems off, check the official docs for the target's support status (verified as of Unity 6 / 6000.0 for this article).

Building Blocks of Shader Graph

ElementDescription
Shader Graph assetThe file that stores the shader's configuration
BlackboardThe list of properties and keywords
Master StackThe final output to the shader
NodeA unit of shader processing
PropertyAn external parameter of the shader
Sub GraphA reusable part

Types of Shader Graph Assets

TypeUse
Unlit Shader GraphNot affected by lighting (for UI and effects)
Lit Shader GraphAffected by lighting (for PBR materials)

Structure of the Master Stack

The Master Stack consists of two stages:

Diagram of the Master Stack structure. The Vertex stage handles moving vertices, the Fragment stage handles deciding color. The results of your connected nodes gather here to become the shader's output
StageProcessingTypical Uses
VertexVertex shader processingVertex animation, position deformation
FragmentFragment shader processingColor, textures, lighting

Position port: By connecting to the Position port of the Vertex stage, you can deform vertex positions (rippling water surfaces, grass swaying in the wind, and so on).

PBR Parameters of the Lit Shader Graph

ParameterDescription
Base ColorThe base color
NormalNormal map (surface detail)
MetallicMetalness (0 = non-metal, 1 = metal)
SmoothnessSmoothness (0 = rough, 1 = glossy)
EmissionEmission color
Ambient OcclusionAmbient occlusion (shadow intensity)
AlphaTransparency (used with the Transparent setting)

Setting Up Transparent and Semi-Transparent Materials

To create glass or semi-transparent materials:

  1. Select the Shader Graph and open the Graph Inspector
  2. Change Surface Type to Transparent
  3. Connect the transparency value to the Alpha port of the Master Stack (0 = fully transparent, 1 = opaque)

Key Graph Inspector settings:

SettingOptionsPurpose
Surface TypeOpaque / TransparentOpaque / transparent rendering
Render FaceFront / Back / BothWhich faces to render
Alpha ClippingOn / OffTexture cutout
Two SidedOn / OffDouble-sided rendering
Cast ShadowsOn / OffShadow casting

Alpha Clipping: For cutout textures such as leaves or grass, enable Alpha Clipping and set the Alpha Clip Threshold.

Sponsored

Creating a Shader Graph and Basic Operations

Creating a Shader Graph Asset

  1. Right-click in the Project window
  2. Select Create > Shader Graph > URP > Unlit Shader Graph
  3. Double-click the asset to open the editor

Creating and Connecting Nodes

  1. Right-click in the workspace → Create Node
  2. Search for a node in the search field
  3. Drag from a node's output port to an input port on the Master Stack

Creating and Applying a Material

  1. Right-click the Shader Graph asset → Create > Material
  2. Drag and drop the created material onto an object

Dynamic Shaders with Properties

Adding a Property

  1. Click the + button on the Blackboard
  2. Choose the property type (Color, Float, Texture2D, etc.)
  3. Drag and drop the property into the Shader Graph window

Changing Colors from a Script

// Method 1: modify material directly (creates a material instance)
renderer.material.SetColor("_Main_Color", Color.red);

// Method 2: MaterialPropertyBlock (preserves batching, recommended)
var mpb = new MaterialPropertyBlock();
renderer.GetPropertyBlock(mpb);
mpb.SetColor("_Main_Color", Color.red);
renderer.SetPropertyBlock(mpb);

SRP Batcher and MaterialPropertyBlock (for how the SRP Batcher works, see Draw Calls and Batching):

  • With the SRP Batcher enabled, using a MaterialPropertyBlock breaks SRP Batcher batching
  • Small number of objects → MaterialPropertyBlock is fine
  • Large number of objects → material instances may benefit more from the SRP Batcher
  • Choose the approach that fits your use case

Important: About Reference names When accessing a property from a script, use the Reference name set on the Blackboard. Select the property in the Blackboard and check the Reference field in the Graph Inspector. By default it takes the form _PropertyName (e.g. Main Color_Main_Color; spaces are converted to underscores). You can freely change the Reference name in the Graph Inspector.

Shaders Using Textures

  1. Add a Texture2D property
  2. Add a Sample Texture 2D node
  3. Connect the property to the Texture input
  4. Connect the RGBA output to Base Color
Sponsored

Scrolling Textures

This is the entry point to "shaders that move." Flowing rivers, conveyor belts, drifting background clouds — feed the time from a Time node into the UV offset, and the texture scrolls endlessly.

Node setup for a scrolling texture. A Time node goes through Multiply for speed adjustment into the Offset of Tiling and Offset, whose output connects to the UV of Sample Texture 2D, making the texture scroll forever
  1. Add a Time node (gets the current time)
  2. Add a Vector2 node (apply time to the X axis only)
  3. Add a Tiling and Offset node
  4. Connect the Vector2 output to the Offset input
  5. Connect it to the UV input of Sample Texture 2D

Use a Multiply node to adjust the speed.

Commonly Used Nodes

Input Nodes

NodeDescription
TimeGets the current time (for animation)
UVGets the mesh's UV coordinates
PositionGets the vertex position

Texture Nodes

NodeDescription
Sample Texture 2DSamples a texture
Tiling and OffsetApplies tiling and offset to UV coordinates

Math Nodes

NodeDescription
Add, Subtract, Multiply, DivideBasic arithmetic operations
LerpLinear interpolation
ClampRestricts a value to a range

Procedural Nodes

NodeDescription
NoiseGenerates noise
CheckerboardGenerates a checkerboard pattern
GradientGenerates a gradient
Fresnel EffectView-angle-based effect (rim lighting, holograms)

Fresnel Effect Power value:

  • Small values (1-2) → the effect spreads over a wide area (the whole surface glows)
  • Large values (5-10) → the effect concentrates on the edges only (sharp rim light)
Rim-light comparison of the Fresnel Effect. With a small Power value the sphere glows softly across its whole surface; with a large Power value only the outline (edges) glows sharply. The basis of hologram and rim-light effects

Creating Sub Graphs

A Sub Graph lets you bundle multiple nodes into a reusable part.

How to Create One

  1. Right-click in the Project window → Create > Shader Graph > Sub Graph
  2. Define the inputs and outputs in the Sub Graph editor
  3. Connect the processing nodes
  4. Save it and use it in other Shader Graphs

Use Cases

  • Shared noise generation logic
  • UV manipulation patterns
  • Shared color conversion logic

Example: A UV Rotation Sub Graph

I/ONameType
InputUVVector2
InputAngleFloat
OutputRotatedUVVector2

Processing: Use a Rotate node to rotate the UVs by Angle degrees and output the result as RotatedUV. You can reuse it for texture rotation animations and more.

Advanced Features

Keywords (Conditional Branching)

Keywords enable #ifdef-style conditional branching inside a shader.

  1. Click + on the Blackboard → select Keyword
  2. Choose the type: Boolean, Enum, or Built-in
  3. Drag the Keyword into the graph and a Keyword node is generated automatically
  4. Connect different processing to each output of the Keyword node

Optimization: With Keywords, different shader variants are compiled depending on the condition, letting you skip unnecessary processing.

Custom Function Node

This node lets you write HLSL code directly. Use it to add processing that Shader Graph alone can't achieve.

  1. Right-click → Create Node → search for Custom Function
  2. Write the HLSL code in a file or inline
  3. Define the inputs/outputs and connect them

Next step: If you know HLSL, try tackling advanced effects with the Custom Function Node.

Common Problems and Solutions

SymptomCause and Fix
Material turns pinkShader compile error. Check the errors in the Graph Inspector
Material is completely blackNothing is connected to Base Color, or the Normal Map format is not set
Not becoming transparentSurface Type is still set to Opaque
Normal Map doesn't look purpleSet the Texture Type to "Normal map" in the texture's Import Settings

Shader variants: Adding Keywords increases the number of shader variants exponentially (up to 2^n variants for n Boolean keywords). For mobile, it's recommended to strip unnecessary variants in Graphics Settings.

Practical: Building a Damage-Flash Shader

When you slash an enemy in an action game, when a bullet hits the boss in a shmup, when an attack lands in an RPG — that classic effect where the enemy flashes white for an instant is a perfect practice piece for Shader Graph. It brings together the whole flow you learned in this article: "create a property → wire up nodes → drive it from a script."

The mechanism is a single Lerp. Blend the normal color and pure white using FlashAmount (0-1) — 0 shows the normal look, 1 shows pure white, and bumping this value up for just a moment from a script gives you the "flash."

Node setup for the damage-flash shader. The output of Sample Texture 2D and a white color are blended by a Lerp node with the FlashAmount property as the factor, then output to Base Color

Building the graph (3 steps):

  1. Add two properties on the Blackboard: MainTex (Texture2D) and FlashAmount (Float, Reference name _FlashAmount, default 0)
  2. Read the texture with Sample Texture 2D and connect it to input A of a Lerp node. Connect a Color node (white) to B
  3. Connect FlashAmount to the Lerp's T input, and route the output to the Master Stack's Base Color

After that, all you do is drive _FlashAmount from a script. This is where the MaterialPropertyBlock introduced earlier pays off.

// DamageFlash.cs (attach to the enemy)
using System.Collections;
using UnityEngine;

public class DamageFlash : MonoBehaviour
{
    [SerializeField] private float flashDuration = 0.1f;

    private Renderer rend;
    private MaterialPropertyBlock mpb;
    private static readonly int FlashAmount = Shader.PropertyToID("_FlashAmount");

    void Awake()
    {
        rend = GetComponent<Renderer>();
        mpb = new MaterialPropertyBlock();
    }

    // Call this from your damage handling
    public void Flash()
    {
        StopAllCoroutines();
        StartCoroutine(FlashRoutine());
    }

    private IEnumerator FlashRoutine()
    {
        SetFlash(1f); // go pure white
        yield return new WaitForSeconds(flashDuration);
        SetFlash(0f); // back to normal
    }

    private void SetFlash(float amount)
    {
        rend.GetPropertyBlock(mpb);
        mpb.SetFloat(FlashAmount, amount);
        rend.SetPropertyBlock(mpb);
    }
}

Call damageFlash.Flash() from the enemy's damage handling and you're done. Because it uses a MaterialPropertyBlock, even with 100 enemies the material stays a single one — each enemy can flash on its own timing.

There are two key points: "build a look-switch from Lerp plus a 0-1 property" (not just white flashes — freeze, poison, stealth, and most other state effects take this same shape), and "touch script-facing values by their exact Reference name" (a typo in _FlashAmount won't raise an error — it just silently does nothing, so be careful). If coroutines are fuzzy for you, check that out too.

Summary

Shader Graph is a powerful tool that lets you create shaders without programming.

  • Node-based - Build complex shaders just by connecting nodes
  • Real-time preview - See the results of your changes instantly
  • Properties - Adjust values from the material, and change them from scripts too
  • Sub Graphs - Reuse shared parts
  • The basic form of a state effect is Lerp plus a 0-1 property. The damage flash is your first step

Start with simple things like changing colors or displaying textures, then gradually move on to animations and effects. Your game's enemies — do they actually look like it "hurts" when they take a hit?

What to Read Next