- Home /
Can you change Alpha and Blue(rbg) simultaneously?
Going largely off of aldonaletto's answer on:
http://answers.unity3d.com/questions/328891/controlling-duration-of-colorlerp-in-seconds.html
I'm attempting to fade in/out my GUIText while at the same time lerping the color from white to yellow. Using the following script:
#pragma strict
var startColor : Color;
var endColor : Color;
var warningText : GUIText;
var duration: float = 2; // duration in seconds
var t: float = 0; // lerp control variable
function Start()
{
warningText.material.color.a = 0; // hides warning text
startColor = Color.white;
endColor = Color.yellow; //sets color of warning text
}
function Update()
{
if(conditions are met ex: close to detection, low health)
{
Fade();
ColorSwap();
}
if(conditions are not met)
{
warningText.material.color.a = 0; //hide text
}
}
function Fade()
{
while (warningText.material.color.a < 1) //fade in
{
warningText.material.color.a += 0.005 * Time.deltaTime * 1;
yield;
}
yield WaitForSeconds(1);
while (warningText.material.color.a > 0) //fade out
{
warningText.material.color.a -= 0.005 * Time.deltaTime * 1;
yield;
}
}
function ColorSwap()
{
t += Time.deltaTime/duration;
warningText.material.color = Color.Lerp(startColor, endColor, t); //goes white ->yellow
yield WaitForSeconds(2.5); //pauses at yellow for .5 seconds because duration is 2 seconds
warningText.material.color = Color.Lerp(endColor, startColor, t); //goes yellow ->white
}
When using each function separately they work. Which leads me to believe that you can't change color/alpha at the same time. Or is there something I'm doing wrong?
Answer by wibble82 · Mar 18, 2014 at 03:51 PM
Your issue is that in the ColorSwap function you are setting the colour of the material to a new value each frame. The colour encodes both rgb AND alpha, so you are effectively going:
in Fade(): set the alpha of my material to account for fading
in ColourSwap(): set the colour of my material to the new colour, AND the alpha to 1
You could do this various ways, your simplest probably being to just set the rgb part of material.color in ColorSwap() to something like:
//save current alpha
float current_alpha = warningText.material.color.a;
//overwrite colour with new one
warningText.material.color = Color.Lerp(startColor, endColor, t);
//restore alpha (as we only wanted to overwrite the rgb components)
warningText.material.color.a = current_alpha;
Maybe put that code in a function and call it twice from your colour swap. So you might have a function that went:
void SetWarningTextMaterialColor(Color new_col)
{
//save current alpha
float current_alpha = warningText.material.color.a;
//overwrite colour with new one
warningText.material.color = new_col;
//restore alpha (as we only wanted to overwrite the rgb components)
warningText.material.color.a = current_alpha;
}
And then your set colour function would be:
void ColorSwap()
{
t += Time.deltaTime/duration;
SetWarningTextMaterialColor(Color.Lerp(startColor, endColor, t)); //goes white ->yellow
yield return new WaitForSeconds(2.5); //pauses at yellow for .5 seconds because duration is 2 seconds
SetWarningTextMaterialColor(Color.Lerp(endColor, startColor, t)); //goes yellow ->white
}
Just realised, I replied in c# to your javascript question! sorry - it should be very easy to convert though. Hopefully the principle is clear anyhoo :)
As a side note, I'm not convinced your code does what you expect it to it looks like it'll just set the colour once, wait 2.5s, then set it again. Presumably you're after a gentle fade from one colour to another over a period of time? There's actually a lot of random yields in there - are you clear on what they mean?
haha sorry about the yields :(, this isn't the exact script because $$anonymous$$onodevelop is freaking out on me, so I was trying to quickly type it off the top of my head and just forgot to delete the yields (they were meant to be WaitForSeconds that I deleted after I realized they were in the wrong place). But you are correct that I'm looking for a gentle fade, and after running the script I posted above you are correct that it only switches once. I didn't know that about the RBG and alhpa so that is VERY useful to know:D . I'll try implementing what you wrote, seems very promising.
Thanks for your answer, it worked well after some tinkering.
Answer by poncho · Mar 18, 2014 at 03:47 PM
Yes, they can, you are lerping colors from White to Yellow, both have Alpha as 1 and both are RGB(Red, Green, Blue) colors, not RGBA(Red, Green, Blue, Alpha), change the endColor's alpha to desired ending alpha
How would that look? as a quick 1-line example. I'm not very confident with my understanding of Color.Lerp
Answer by robertbu · Mar 18, 2014 at 03:57 PM
In your ColorSwap(), you apparently want to fade to/from yellow over time, yet you don't put while loops in like you've done for Fade():
function ColorSwap()
{
var t : float = 0.0;
while (t < 1.0) {
warningText.material.color = Color.Lerp(startColor, endColor, t);
yield;
t += Time.deltaTime/duration;
}
warningText.material.color = endColor;
yield WaitForSeconds(2.5); //pauses at yellow for .5 seconds because duration is 2 seconds
t = 0.0;
while (t < 1.0) {
warningText.material.color = Color.Lerp(endColor, startColor, t); //goes yellow ->white\
yield;
t += Time.deltaTime/duration;
}
warningText.material.color = startColor;
}
Note you have pseudo-code here:
if(conditions are met ex: close to detection, low health)
{
Fade();
ColorSwap();
}
But you want to be very careful that once conditions are met, you only call these two functions once; It is easy given the structure of your code here to be calling them every frame. That would result in lots of coroutines all running at the same time...around 400 if you are running at 60 fps.
if I had a statement in Update ()like:
if(currentHealth < 20)
{
Fade();
ColorSwap();
}
Wouldn't it only have the coroutines run while currenthealth is less than 20?
No. no. no. This will not work...or more correctly, it will sorta-work but have serious issues. A coroutine (in Javascript any fucntion that has a yield) is created each time the function is called. That coroutine exists until it finishes. So 'ColorSwap()' takes 6.5 seconds to run. Assu$$anonymous$$g currentHealth remains below 20 for the 6.5 seconds, you will be creating a new coroutine each time ColorSwap() is called. So running at 60 fps, in 6.5 seconds you will call ColorSwap() 390 times. That means you will have 390 coroutines, all offset by one deltaTime in terms of their ti$$anonymous$$g, running at the same time, all trying to adjust the color. At the end of 6.5 seconds, the first one completes, but as long as currentHealth < 20, you will still be creating new ones...so you will continue to have 390 coroutines running until the health is again above 20.
A fix is to use a boolean variable. Something like:
if (currentHealth < 20 && !fadeSwap) {
Fade();
ColorSwap();
fadeSwap = true;
}
if (currentHealth >= 20) {
fadeSwap = false;
}
Even this code as a bit of a hole in that if the health goes above 20 and then again down below 20 in less than 6.5 seconds, you could end up with two ColorSwap() coroutine running at the same time.
okay I get that, and to avoid it being called twice, create a 7ish second timer and check that the timers expired before being able to call it again. This is really helpful to know, time to go fix some code.
Rather than a 7 second timer, you could put a boolean value like 'swapping' at the top of the file and set it to true at the top of ColorSwap() and false at the bottom. That way you would know when the coroutine is running.
Or you could just have ColorSwap() clear the 'fadeSwap' flag when it finished, but if you do that and currentHealth < 20, then the Coroutine will fire again.
Your answer