Skip to content

How to Animate Materials

If you are more of a visual learner there’s also a video tutorial:

The custom material inspector properties can be animated through the Animation window as any other Unity component.

Please keep in mind that UI material properties can’t be animated using the Animator, the reason being that Unity won’t allow you to animate shared material properties. Unity UI Images materials are always shared, which means that all Images use the exact same material instance of a particular Image and therefore if a property is changed for one Image material all the other Images that share material will change too. Since Unity won’t allow this behaviour it doesn’t support using the Animator in UI Material properties. And unfortunately I can’t do anything about it.

I recommend using an amazing free asset in the store called DOTween to animate the UI material properties through code. There are worked examples further down this page.

Also consider that since UI material instances are shared you may want to create a copy of each material through script on an Awake method (AllIn1GraphicMaterialDuplicate.cs):

private void Awake()
{
Graphic graphic = GetComponent<Graphic>();
graphic.material = new Material(graphic.material);
}

DOTween can tween a material property directly, which makes it the easiest route for UI and for anything you want to trigger from code. It is free on the Asset Store, and everything below needs using DG.Tweening;.

Enable the effect in the Material Inspector first. Tweening a property does nothing while its effect is off.

Dissolving an effect out, driving _FadeAmount from untouched to fully gone:

using UnityEngine;
using DG.Tweening;
public class DissolveOnCall : MonoBehaviour
{
private Material mat;
private void Awake()
{
mat = GetComponent<Renderer>().material;
}
public void Dissolve()
{
mat.SetFloat("_FadeAmount", -0.1f);
mat.DOFloat(1f, "_FadeAmount", 1f).SetLink(gameObject);
}
}

SetLink(gameObject) kills the tween if the object is destroyed. Without it a tween outliving its material throws.

For something that fires, waits, and fires again in the same direction, use a Sequence with LoopType.Restart. Yoyo would run the second half backwards, which is usually not what a pulse should look like.

using UnityEngine;
using DG.Tweening;
public class RimPulse : MonoBehaviour
{
[SerializeField] private float riseDuration = 0.4f;
[SerializeField] private float pauseBetween = 1.5f;
private Sequence sequence;
private void Start()
{
Material mat = GetComponent<Renderer>().material;
sequence = DOTween.Sequence();
sequence.AppendCallback(() => mat.SetFloat("_RimIntensity", 0f));
sequence.Append(mat.DOFloat(4f, "_RimIntensity", riseDuration));
sequence.AppendInterval(pauseBetween);
sequence.SetLoops(-1, LoopType.Restart);
sequence.SetLink(gameObject);
}
}

The callback resets the property at the top of every loop, so each pass starts from the same place no matter where the previous one ended. The same shape works for any property: _ColorRampBlend, _Alpha, a shape scroll speed, whatever the effect needs.

Same code, with the two UI rules above. Copy the material in Awake so the tween does not move every Image sharing it, and if the Image is masked, tween materialForRendering instead:

Material mat = image.materialForRendering;
mat.DOFloat(1f, "_FadeAmount", 1f).SetLink(gameObject);