How Do I Smoothly Change The Color Of The SpriteRenderer Over Time?

Hi friends, thanks for taking the time to look at my question.

I have a “tile” that when clicked fluctuates between an “on” state and “off” state. As a visual cue, I would like the tiles to have an “on color” and an “off color”.

My understanding is that I would need to use Color.Lerp - lerping between the sprite’s current color and the desired color.

I’ve done so in my code here,

public class testclick : MonoBehaviour
{
bool isOn = true;
public Color on_color;
public Color off_color;
private SpriteRenderer sr;
private float timeLeft = 0f;

 void Awake()
 {
     sr = gameObject.GetComponent<SpriteRenderer>();
 }

 void Update()
 {
     Debug.Log("Updating...");
     if (timeLeft > 0)
     {
         Debug.Log($"IsOn: {isOn}");
         if (isOn)
         {
             Color c = Color.Lerp(on_color, sr.color, timeLeft);
             sr.color = new Color(c.r, c.g, c.b, 3);
             Debug.Log($"{c.r}, {c.g}, {c.b}");
         }
         else
         {
             Color c = Color.Lerp(off_color, sr.color, timeLeft);
             sr.color = new Color(c.r, c.g, c.b, 3);
             Debug.Log($"{c.r}, {c.g}, {c.b}");
         }
         timeLeft -= Time.deltaTime;
     }
 }

 void OnMouseDown()
 {
     timeLeft = 0.2f;
     isOn = !isOn;
 }

}

but what results is NOT a smooth transition. What do I need to do to make this more fluid, and less choppy?

Thanks again!

The 4th argument of the Color.Lerp function is meant to be a float between 0 and 1.

If this argument is 0, the function returns the 1st color

If this argument is 1, the function returns the 2nd olor

If this argument is a value between 0 and 1, the function returns a color computed as a blend between the 1st and 2nd color.

In your case, it seems that timeLeft can will be equal to 0.2 at most.

So, either ensure this variable can reach 1 and just change the “speed” the value change:

  void Update()
  {
      Debug.Log("Updating...");
      if (timeLeft > 0)
      {
          Debug.Log($"IsOn: {isOn}");
          if (isOn)
          {
              Color c = Color.Lerp(on_color, sr.color, timeLeft);
              sr.color = new Color(c.r, c.g, c.b, 3);
              Debug.Log($"{c.r}, {c.g}, {c.b}");
          }
          else
          {
              Color c = Color.Lerp(off_color, sr.color, timeLeft);
              sr.color = new Color(c.r, c.g, c.b, 3);
              Debug.Log($"{c.r}, {c.g}, {c.b}");
          }
          timeLeft -= Time.deltaTime * 5; // To keep a lerp time of 0.2 seconds
      }
  }
 
  void OnMouseDown()
  {
      timeLeft = 1f;
      isOn = !isOn;
  }

OR, get rid of Color.Lerp and timeLeft and use Vector4.MoveTowards instead, because you can convert a Color from and to Vector4

  void Update()
  {
      Debug.Log($"IsOn: {isOn}");
      if (isOn)
      {
          Color c = Vector4.MoveTowards(on_color, sr.color, Time.deltaTime * 5);
          sr.color = new Color(c.r, c.g, c.b, 3);
          Debug.Log($"{c.r}, {c.g}, {c.b}");
      }
      else
      {
          Color c = Vector4.MoveTowards(off_color, sr.color, Time.deltaTime * 5);
          sr.color = new Color(c.r, c.g, c.b, 3);
          Debug.Log($"{c.r}, {c.g}, {c.b}");
      }
  }
 
  void OnMouseDown()
  {
      isOn = !isOn;
  }