- Home /
Color.Lerp doesn't go until white. Why?
I have this code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GrowPlayer : MonoBehaviour {
private const string DESERT_STRING = "Desert";
private const string SNOW_STRING = "Snow";
private const float COLOR_STEP = (float)0.01;
private const float LERP_STEP = (float)0.01;
public Color myRed = new Color((float)0.9411765, (float)0.1960784, (float)0.1960784);
public Color myYellow = new Color((float)0.8529412, (float)0.8529411, (float)0.3073097);
public Color myGreen = new Color((float)0.2117647, (float)0.4588236, (float)0.244138);
public Color myWhite = new Color((float)1,(float)1,(float)1);
private List<GameObject> areasList = new List<GameObject>();
public Color thisColor;
// Use this for initialization
void Start () {
foreach (Transform child in transform) {
child.gameObject.AddComponent<GrowPlayer>();
}
GameObject[] objects = GameObject.FindGameObjectsWithTag(DESERT_STRING);
foreach (GameObject go in objects) {
areasList.Add(go);
}
objects = GameObject.FindGameObjectsWithTag(SNOW_STRING);
foreach (GameObject go in objects) {
areasList.Add(go);
}
}
// Update is called once per frame
void Update () {
thisColor = renderer.material.color;
colorChange();
}
void colorChange () {
bool findedOne = false;
foreach(GameObject area in areasList) {
if (area.collider.bounds.Contains(renderer.transform.position)) {
findedOne = true;
switch (area.tag) {
case DESERT_STRING:
goToColor(myYellow);
break;
case SNOW_STRING:
goToColor(Color.white);
break;
default:
goToColor(myGreen);
break;
}
}
if (!findedOne) {
goToColor(myGreen);
}
}
}
void goToColor(Color color) {
renderer.material.color = Color.Lerp(renderer.material.color, color, LERP_STEP);
}
}
It changes the renderer color depending on where it is. It works how it should for "myYellow" and "myGreen", but it never reaches the white color, it stops much before becoming white. Does anyone knows what could be the problem?
Not sure if this is the issue, but the way you are using Color.Lerp() produces an eased movement towards the color. It can take a really long time to reach the end value. Also you are not using a Time.delaTime adjusted value, so your fade to the color may be uneven.
Answer by Maerig · Jun 30, 2014 at 06:25 AM
This is a tricky logic issue. Let's execute the algorithm manually supposing the following :
The
gameObject
is only contained in an area with the "Snow" tagThe
areasList
member contains those gameObjects, in this order :GameObject
with the "Desert" tag
GameObject
with the "Snow" tagbool findedOne = false;
First, findedOne
is set to false
.
foreach(GameObject area in areasList) {
Then, the algorithm iterates through the list. The first item is the desert area, so
(area.collider.bounds.Contains(renderer.transform.position))
is false. However,
!findedOne
is true, so
goToColor(myGreen);
will be executed. Then, in the next foreach
iteration
area.collider.bounds.Contains(renderer.transform.position)
is true, so eventually
goToColor(Color.white);
will be executed too.
To fix it, you just need to take
if (!findedOne) {
goToColor(myGreen);
}
out of the foreach
loop, like this
void colorChange () {
bool findedOne = false;
foreach(GameObject area in areasList) {
if (area.collider.bounds.Contains(renderer.transform.position)) {
findedOne = true;
switch (area.tag) {
case DESERT_STRING:
goToColor(myYellow);
break;
case SNOW_STRING:
goToColor(Color.white);
break;
default:
goToColor(myGreen);
break;
}
/* (Optional) Exit the foreach loop, so that it doesn't
keep on looking for an intersected area once one has
been found */
break;
}
}
// Only fade to green if the gameObject isn't contained in any area
if (!findedOne) {
goToColor(myGreen);
}
}
This way, the gameObject
will only fade to green if it isn't contained in any area.
Does that help ?
I wouldn't call it a logic issue. I would call an attention issue. The green change should be out of the loop from the beginning. I didn't notice I have put it inside the loop by mistake. Thank you.
Answer by hav_ngs_ru · Jun 29, 2014 at 08:09 AM
Lerp usage: Lerp(srcColor, targetColor, dt);
if dt == 0 - you will got a srcColor as result
if dt == 1 - you will have a targetColor as result
if 0 < dt < 1 - you will have a color between src and target color (smaller dt - color much like a src, greater dt - color much like a targetColor)
in your case you will endlessly approach targetColor but never reach it.
@hav_ngs_ru - the OP source is a non-traditional use of Lerp(), but it is used and many examples on this site. It works by updating the start position each frame, and moving some fraction of the distance towards the goal. In this case the fraction is 0.01. So each frame the same fraction is moved, but that fraction represents ever decreasing values as the Color moves towards the destination color.
robertbu, yes, such use of Lerp is clear for me, but question was - why color does not reach the destination. the answer is - because in this case the color change slows down when approaching the destination, and the speed drops to zero just before reaching the "white color". so if the goal is to reach white color - there is at least two ways: to change color linearly, or increase the fraction if its important to change color this way (such in code).
Your answer
Follow this Question
Related Questions
Color.lerp not working properly 2 Answers
How do you Lerp light.color into multiple colors? 2 Answers
Change Color of Children Based on Parent 0 Answers
Change slider color to green when value is 50 2 Answers
Not exact color 1 Answer