Updating a material color with both an animator and script

Hello,

I want to change the color of the same renderer material in two ways:

  • Through script (depends on runtime data)
  • With an animator (in the case I want to show an error, then my material blinks red)

The problem is that it works correctly, until I use the animator; then the material keeps the last color set by the animator, even if I try to update it through script (I debugged the script and it works as expected).

Here is a simplified version of my script:

public class TileColor : MonoBehaviour {
	[SerializeField] protected MeshRenderer _renderer;
	[SerializeField] protected Animator     _animator;

	public Color color { get; set; }

	// I call this function to start the error-blinking animation, managed by the animator
	public void BlinkError() {
		_animator.enabled = true;
		_animator.SetTrigger("Error");
	}

	// This function is called by an animation event when the animation ends
	public void EndAnimation() {
		_animator.enabled = false;
	}

	private void Update() {
		if (_animator.enabled) return;
		_renderer.material.color = color;
	}
}

Anyone got an idea?

A bit of a late answer but I just ran into this problem myself. For anyone out there googling, here’s the solution:

The animator uses MaterialPropertyBlocks to modify the shared material for rendering so even if you set the material’s color in the script, the block’s color overrides the material’s color so the thing to do is overwrite the block in LateUpdate like so:

void LateUpdate()
{
    if(_animator.enabled) return;
    MaterialPropertyBlock block = new MaterialPropertyBlock();
    _renderer.GetPropertyBlock(block);
    block.SetColor("_Color", color);
    _renderer.SetPropertyBlock(block);
}