Unity: Easy Shader Property Access

There is a wide range of shaders for visual effects in games. Since the release of Shader Graph, the creation of shaders has become more accessible for non-programmers. This has raised the question: how do you set shader variables if you can’t code?

 

Whenever you want to set/get a shader variable you should do some caching to minimize the impact on runtime performance. This is important if the variable is set in each frame (update loop).

 

Approach

A C# class that can be initialized with the shader variable name and its type is handy for programmers that don’t want to write the caching code each time. But this may be a bit too much for a visual artist. A simple solution would be a component which can be configured in the inspector. This eliminates the need for a script. Shader properties that are simple enough to be handled in the inspector include:

 

  • float
  • int
  • color
  • matrix
  • texture
  • vector

I have implemented class and component access for these shader properties. It can be found on my GitHub and is open-source (MIT). If you need access to the buffers or array versions of the properties feel free to extend my implementation.

 

Component Access

The setup for the component is easy. Just add it to a gameObject, and set the reference to the renderer and the property name. Now the property can be set/get on the component or added to a unity event.

 

Left the component used to access the tint property of the default sprite shader. On the right is an example of how to use the component in combination with a Unity Event.

 

Script Access

If you want to use it in code look at the following example. It’s a simple script that sets the tint property (shader property name: _Color) of the default sprite shader.

 

On the left, the set-up in the hierarchy and the changing sprite is on the right.

 

using UnityEngine;

public class ShaderAccessExample : MonoBehaviour
{
  [SerializeField]
  private SpriteRenderer spriteRenderer;

  [SerializeField]
  private float duration = 3f;

  private float elapsedTime = 0;

  private ShaderColorAccess colorAccess;

  void Start()
  {
    colorAccess = new ShaderColorAccess(spriteRenderer, "_Color");
  }

  void Update()
  {
    elapsedTime += Time.deltaTime;
    elapsedTime %= duration;

    Color newColor = Color.Lerp(Color.yellow, Color.blue, elapsedTime / duration);

    colorAccess.Set(newColor);
  }
}