# Using Lerp to create a hovering effect for a GameObject

I want to have a GameObject that has a "hovering" effect when the mouse is over it.

What I'm having trouble with is actually having a color that gradually goes from one color to the next. I'm assuming Color.Lerp() is the best function for that, but I can't seem to get it working properly.

Here's my CubeBehavior.cs's Update() function:

private bool ReachedTop = false;
private float t = 0f;
private float final_t;
private bool MouseOver = false;

// Update is called once per frame
void Update () {
if (MouseOver) {
t = Time.time % 1f; // using Time.time to get a value between 0 and 1
if (t >= 1f || t <= 0f) // If it reaches either 0 or 1...
ReachedTop = ReachedTop ? false : true;

if (ReachedTop) final_t = 1f - t; // Make it count backwards
else final_t = t;

print (final_t); // for debugging purposes
renderer.material.color = Color.Lerp(Color.red, Color.green, final_t);
}
}

void OnMouseEnter() {
MouseOver = true;
}

void OnMouseExit() {
renderer.material.color = Color.white;
MouseOver = false;
}


Now, I've tried several approaches to making it reach 1 then count backwards till 0 including a multiplier that alternates between 1 and -1, but I just can't seem to get that effect. The value goes to 1 then resets at 0.

Any ideas on how to do this?

• not exactly sure what kind of "hover" effect you want to achieve, could you be more specific? – user13213 Jul 5 '12 at 11:07
• @melak47 The code is self explanatory: hovering over the cube would make it change colors, slowly and gradually between (in this example) red and green; it starts red/green, slowly becomes a cross of both, and eventually becoming the other color. I don't care which starts. That's actually irrelevant anyways; the real question is how do I use Time.time (or any better replacement you can think of) to have a number that goes from 0 to 1 as a float, and when reaches 1, changes direction and counts backwards to 0, (0.9->0.8->0.7->...) and the repeats the other way around. – casraf Jul 5 '12 at 11:14
• As a longer-view heads up, by the way: now that you have the basics of your color interpolation working, you'll probably want to replace your Color.Lerp call with a custom call to interpolate between two colors. The issue is that interpolation between colors in RGB space tends to give really ugly intermediate colors (e.g., red to green goes through brown). At the very least you should interpolate in something like HSV (Hue-Saturation-Value) coordinates; for an even more detailed approach, check out the blog post at stuartdenman.com/improved-color-blending . – Steven Stadnicki Jul 5 '12 at 18:10

Found the solution... Just used my own float instead of using Time.time.

private bool CountBack = false;
private float Speed = 0.01f;
private float t = 0f;
private float final_t;
private bool MouseOver = false;

// Update is called once per frame
void Update () {
if (MouseOver) {
if (!CountBack) {
t += Speed;
if (t >= 1f) CountBack = true;
}
else {
t -= Speed;
if (t <= Speed) CountBack = false;
}
final_t = t;
print (CountBack + "("+final_t+")");
renderer.material.color = Color.Lerp(Color.red, Color.green, final_t);
}
}

• you can mark your own answer, it looks good – dreta Jul 5 '12 at 12:39
• @dreta Only lets me do it in 2 days so I'll come back to it – casraf Jul 5 '12 at 12:59

I don't think if (t >= 1f || t <= 0f) is ever executed, have you tried stepping through it with a debugger?

For sure t >= 1f is never going to be true, because of how % works. t <= 0f is going to be true in extremely rare situations, it's definetly never going below 0 and i daubt it'll ever reach zero simply because you're dealing with finite precision.

If i was to suggest something, try using 0.9 instead of 1 and 0.1 instead of 0 or something, i've no idea how precise the timer you're using is. The rest of the logic should work fine.

EDIT: The author answered his own question, still i'm leaving a different solution to this in C++.

#include <iostream>

int main () {

float i = 0.f, final_i;
bool swap = false;

for(unsigned int k = 0; k < 30; ++k){

i += 0.1f;

if ( i >= 1.f ) {
i = 0.f;
swap = swap ? false : true;
}

if ( swap ) {
final_i = 1.f - i;
}
else{
final_i = i;
}

std::cout<<final_i<<std::endl;
}

system("pause");

return 0;
}

• Debugging this did work and the variables did change, but I'm not sure if often enough, whatever the result though, it didn't ever do this properly, I'll try to change that, thanks. Can you think of better logic to work it? – casraf Jul 5 '12 at 11:46
• @OhMrBigshot but does the value of ReachedTop change when you step through the code? – dreta Jul 5 '12 at 11:54
• It does. RIght now I simply used return; after changing ReachedTop if it's true, and the effect is much smoother - but it still has jumps now and then (like every 3-4 seconds). I'm using 0.03 and 0.97 for the checks, and anything farther from the integers than that results in a million jumps. – casraf Jul 5 '12 at 12:04

Alternately:

t = Time.time % 2f;
if (t > 1f)
t = 2f - t;


This will also give you a 't' value which smoothly loops back and forth along the interval [0..1..0].

iTween has a ColorTo method that might work as well..

http://itween.pixelplacement.com/documentation.php