Shader Properties

The Properties block of a shader is used to pass values into the shader instance.

Properties may be used in the shader if a matching property variable is defined in the shader body:

Shader "Shaders/Material/Prop" {
  Properties {
    _MainTex ("Texture", 2D) = "white" {}
    _Amount ("Extrusion Amount", Range(-5,5)) = 0.5
    _BumpMap ("Extrusion Map", 2D) = "white" {}
  }
  SubShader {
    Tags { "RenderType" = "Opaque" }
    CGPROGRAM
    #pragma surface surf Standard

    // Match the properties with local variables
    sampler2D _MainTex;
    sampler2D _BumpMap;
    float _Amount;

    ...

    ENDCG
  }
  Fallback "Diffuse"
}

These properties are editable in the material window when the Unity editor is open.

Setting properties at runtime

Shader properties are instanced at runtime, which means they can be set per material instance without any problem.

To set a property you need to first lookup the property id, and then set it to the appropriate type.

var id = Shader.PropertyToId("Name");
if (renderer.material.HasProperty("Name")) {
  renderer.material.SetFloat(id, 0.5f); 
}

There are a variety of methods on Material for setting and getting properties.

Introspection

Introspection on shaders is only available in the editor, for example:

using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace DoubleCam
{
    public class EffectCamera : MonoBehaviour
    {
        [Tooltip("The replacement shader with it's configured shader to use")]
        public Material magicShader;

        [Tooltip("Don't set these manually, add an EnumerateShaderProperties component")]
        public string[] shaderPropertyNames;

        [Tooltip("Don't set these manually, add an EnumerateShaderProperties component")]
        public ShaderPropType[] shaderPropertyTypes;
    }

    /// A non-editor enum of shader property types
    /// ShaderUtils.ShaderPropertyType is not available at runtime.
    public enum ShaderPropType
    {
        UNKNOWN,
        COLOR,
        VECTOR,
        FLOAT,
        RANGE,
        TEX
    }

    [AddComponentMenu("DoubleCam/Enumerate Shader Properties")]
    [RequireComponent(typeof(EffectCamera))]
    [ExecuteInEditMode]
    public class EnumerateShaderProperties : MonoBehaviour
    {
        [Tooltip("Update properties again?")]
        public bool update = true;

        /// Update the properties on the effects camera
        public void Update()
        {
            if (update)
            {
                update = false;
                var effects = GetComponent<EffectCamera>();
                if ((effects != null) && (effects.magicShader != null))
                {
                    var magicShader = effects.magicShader;
                    var shader = magicShader.shader;

                    #if UNITY_EDITOR
                    /// Copy all shader properties over
                    int count = ShaderUtil.GetPropertyCount(shader);
                    effects.shaderPropertyNames = new string[count];
                    effects.shaderPropertyTypes = new ShaderPropType[count];
                    for (var i = 0; i < count; ++i)
                    {
                        var name = ShaderUtil.GetPropertyName (shader, i);
                        var type = ShaderUtil.GetPropertyType(shader, i);
                        effects.shaderPropertyNames[i] = name;
                        effects.shaderPropertyTypes[i] = AsPropType(type);
                    }
                    #endif
                }
            }
        }

        /// Map type to type
        #if UNITY_EDITOR
        private ShaderPropType AsPropType(ShaderUtil.ShaderPropertyType T)
        {
            switch (T)
            {
                case ShaderUtil.ShaderPropertyType.Color:
                    return ShaderPropType.COLOR;
                case ShaderUtil.ShaderPropertyType.Vector:
                    return ShaderPropType.VECTOR;
                case ShaderUtil.ShaderPropertyType.Float:
                    return ShaderPropType.FLOAT;
                case ShaderUtil.ShaderPropertyType.Range:
                    return ShaderPropType.RANGE;
                case ShaderUtil.ShaderPropertyType.TexEnv:
                    return ShaderPropType.TEX;
            }
            return ShaderPropType.UNKNOWN;
        }
        #endif
    }
}