Controlling duration of Color.Lerp in seconds

Hi everyone,

I’;ve asked a question similar to this recently, but it just got me wondering… How can you control the duration of Color.Lerp in seconds?

Take this code for example:

var startColor : Color;
var endColor : Color;

function Update() {
    renderer.material.color = Color.Lerp(startColor, endColor, Time.time);
}

How could modify this so I can explicitely control the duration of the transition in SECONDS?

Thanks in advance. :slight_smile:

The Lerp examples in the docs are terribly bad: using Time.time as the control variable limits things to the first second your game is playing! Ok, you could simply use Time.time/duration instead of just Time.time (duration in seconds), but this would not allow a new sequence without restarting the game.

That’s a simple example that allows duration control and sequence restarting:

var startColor : Color;
var endColor : Color;
var duration: float = 5; // duration in seconds

private var t: float = 0; // lerp control variable
    
function Update() {
  renderer.material.color = Color.Lerp(startColor, endColor, t);
  if (t < 1){ // while t below the end limit...
    // increment it at the desired rate every update:
    t += Time.deltaTime/duration;
  }
}

You can restart the Lerp sequence at any time just assigning 0 to t. A more elaborated version could do it when you press space, for instance:

var startColor : Color;
var endColor : Color;
var duration: float = 5; // duration in seconds

private var t: float = 0; // lerp control variable
    
function Update() {
  if (Input.GetKeyDown("space")){
    t = 0;
  }
  renderer.material.color = Color.Lerp(startColor, endColor, t);
  if (t < 1){ // while t below the end limit...
    // increment it at the desired rate every update:
    t += Time.deltaTime/duration;
  }
}

Hi there.

I’ve not personally used the Color.lerp but I presume it works the same as any lerping function since the 3rd parameter is in the range 0 - 1.

I would recommend using Coroutines for this type of thing. Here is an example:

float duration = 5; // This will be your time in seconds.
float smoothness = 0.02f; // This will determine the smoothness of the lerp. Smaller values are smoother. Really it's the time between updates.
Color currentColor = Color.white; // This is the state of the color in the current interpolation.

void Start()
{
    StartCoroutine("LerpColor");
}

IEnumerator LerpColor()
{
    float progress = 0; //This float will serve as the 3rd parameter of the lerp function.
    float increment = smoothness/duration; //The amount of change to apply.

    while(progress < 1)
    {
       currentColor = Color.Lerp(Color.red, Color.blue, progress);
       progress += increment;
       yield return new WaitForSeconds(smoothness);
    }
}

I haven’t tested the code but I think it’s good enough to demonstrate.
If you don’t know coroutines I would strongly recommend learning about them. It’s very useful for animating things between 2 points. Not just colors but anything. It sure as hell beats keeping track of time variables in update loops.

#Slowly cycle the background color…

It’s remarkably easy to cycle through all the colors of the rainbow:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ColorCycle : MonoBehaviour {

       // put this script on your camera
       // it's great for a Canvas for your UI

	private Camera cam;
	private float cycleSeconds = 100f; // set to say 0.5f to test
	
	void Awake() {
		
		cam = GetComponent<Camera>();
	}
	
	void Update() {
		
		cam.backgroundColor = Color.HSVToRGB(
			Mathf.Repeat(Time.time / cycleSeconds, 1f),
			0.3f,     // set to a pleasing value. 0f to 1f
			0.7f      // set to a pleasing value. 0f to 1f
		);
	}
}

That’s it.

For an object … with proper offset from the editor starting color look, etc.

using UnityEngine;
public class ObjectColorCycle : MonoBehaviour
{
    public Renderer colorMe;

    void Update()
    {
        Colorz();
    }

    float origHue = 0.5f;
    float origSat = 0.5f;
    float origVal = 0.5f;

    void Start()
    {
        Color c = colorMe.material.color;
        Color.RGBToHSV(c, out origHue, out origSat, out origVal);
    }

    private float cycleSeconds = 100f; // as you wish

    void Colorz()
    {
        float h = Mathf.Repeat(origHue + Time.timeSinceLevelLoad / cycleSeconds, 1f);
        colorMe.material.color = Color.HSVToRGB(h, origSat, origVal);
    }
}

That’s easy fortunately.