Reputation:
So i have a button that is suppose to change a colour of an object. Im using color.lerp but i need it to gradually change. like slowly. what i have now:
public Renderer engineBodyRenderer;
public float speed;
public Color startColor, endColor;
float startTime;
// Start is called before the first frame update
void Start()
{
startTime = Time.time;
ChangeEngineColour();
}
public void ChangeEngineColour()
{
float t = (Time.time - startTime) * speed;
engineBodyRenderer.material.color = Color.Lerp(startColor, endColor, t);
}
so the color of the object does change just not slowly. what am i missing?
Upvotes: 2
Views: 8223
Reputation: 1
For this sort of thing I find it best to set the duration instead of using a speed variable.
public Renderer engineBodyRenderer;
public Color startColor, endColor;
public float duration;
private Coroutine changeEngineColorCoroutine;
private void Start()
{
if (changeEngineColorCoroutine != null)
StopCoroutine(changeEngineColorCoroutine);
changeEngineColorCoroutine = StartCoroutine(ChangeEngineColor(startColor, endColor, duration));
}
private IEnumerator ChangeEngineColor(Color _startColor, Color _endColor, float _duration)
{
// start tick 0f so that startColor is shown for a frame
float tick = 0;
while (tick < 1f)
{
// Update color
engineBodyRenderer.material.color = Color.Lerp(_startColor, _endColor, tick);
// Iterate tick after adjusting color so Lerp doesn't use a tick over 1f
tick += Time.deltaTime / _duration;
// Wait a frame
yield return null;
}
// Ensure that the endColor is applied before exit
engineBodyRenderer.material.color = _endColor;
}
Also, if you were calling ChangeEngineColor after Start(), you could initialise tick already iterated for an instantaneous color transition startup as long as startColor is the color already set on the engine.
float tick = Time.deltaTime / _duration;
Upvotes: 0
Reputation: 21
And to change back and forth between colors gradually, replace this line from Fredrick:
engineBodyRenderer.material.color = Color.Lerp(startColor, endColor, tick);
to this:
engineBodyRenderer.material.color = Color.Lerp(startColor, endColor, Mathf.PingPong(Time.time, 1));
So you will have:
Upvotes: 1
Reputation: 5108
In your solution the method is only run ONCE, so only ONE color change can happen. Here's how I usually do it:
void Start()
{
// ... your other stuff
StartCoroutine(ChangeEngineColour());
}
private IEnumerator ChangeEngineColour()
{
float tick = 0f;
while (engineBodyRenderer.material.color != endColor)
{
tick += Time.deltaTime * speed;
engineBodyRenderer.material.color = Color.Lerp(startColor, endColor, tick);
yield return null;
}
}
By starting a Coroutine this code will run asyncronously beside the rest of the code and with yield return null
it will loop in the same speed as your Update()
functions, so essentially you've created an isolated Update() method, that run every frame and will gradually change the color every frame.
Upvotes: 3