- Home /
Mathf.Clamp01 CoRoutine
I'm trying to fade individual pieces of the GUI in C#. Just simple phrases that pop up on the screen and then fade out over time, like small tutorials to my games controls. For this, I took code from a ScreenFade script. My (shortened) code is as follows:
void Awake () {
StartCoroutine(TutorialAddPhrase(3));
c = Color.white;
cDelta = Color.white;
alpha = 1.0f;
fadeSpeed = 1.0f;
fadeDir = -1;
}
void OnGUI () {
print (cDelta.a);
GUI.color = cDelta;
cDelta.a = alpha;
GUI.Label (new Rect (200, 200, 200, 100), "TESTING");
}
void TutorialAddPhrase (int wait) {
yield return new WaitForSeconds(wait);
alpha += fadeDir * fadeSpeed * Time.deltaTime;
alpha = Mathf.Clamp01(alpha);
}
This renders the following error: Assets/Scripts/GUIscript.cs(197,14): error CS1624: The body of GUIscript.TutorialAddPhrase(int)' cannot be an iterator block because
void' is not an iterator interface type
If I change that last function from "void" to "IEnumerator", it doesn't give an error, but it doesn't really properly fade out the alpha. The alpha stops at 0.9863821 (for instance, it differs).
What am I doing wrong here? I hope you can point me in the right direction. I've only just begun working in C#, so it confuses me at times.
Answer by syclamoth · Oct 06, 2011 at 11:35 AM
The problem you are having here, is that StartCoroutine only executes once! That means, that after the WaitForSeconds happens, the bits afterwards don't repeat. Things using Time.deltaTime need to go into the Update or FixedUpdate loops, otherwise they aren't much use to you.
What you probably intended to do, was wait 3 seconds, and then fade the alpha. In order to do that, you need to set up a boolean
bool fading = false;
then in your coroutine, set it to true.
IEnumerator TutorialAddPhrase (int wait) {
yield return new WaitForSeconds(wait);
fading = true;
}
then to do the actual fading, have something in Update:
void Update()
{
if(fading)
{
alpha = Mathf.Clamp01(alpha + (fadeDir * fadeSpeed * Time.deltaTime));
}
}
Another problem is that in your GUI function, you are treating GUI.Color as a reference type, when it is in fact a value type. This means you can't assign GUI.color to some color, and then expect it to change if you change the original- it only assigns what that color is at the exact moment you use it.
Instead, do this-
Color tempColor = new Color(cDelta.r, cDelta.g, cDelta.b, alpha);
GUI.color = tempColor;
It works, thank you very much! And I think I understand what you're saying about the reference/value type, as well. $$anonymous$$akes sense.
One more thing you might want to adjust to your code: the if statement just says "(fading)", ins$$anonymous$$d of "(fading == true)". Thanks again! :D
yeah,
if(fading)
is EXACTLY THE SA$$anonymous$$E as
if(fading == true)
just so you know. If statements always use bool values, and anything else you put in there has to be able to convert into a boolean before the if can handle them- however, actual booleans can just be passed straight in!
I would strongly recommend not using Update, and ins$$anonymous$$d just make the fading happen in the coroutine. That avoids all those awkward "if (fading)" constructions.
@syclamoth: http://www.unifycommunity.com/wiki/index.php?title=Fade A fade doesn't change every frame, it only changes for a given time and then stops. Update is called every frame forever.
@ Eric5h5 : So I've read over your linked article multiple times, but I can't get it to work. In C, I have the following code: StartCoroutine (Fade.use.Alpha(thisObject, 0.0f, 1.0f, 5.0f, EaseType.In)); (thisObject is an assigned variable)
And I get the following error: Object reference not set to an instance of an object
StartCoroutine (Fade.use.Alpha(tut_Add, 0.0f, 1.0f, 5.0f, EaseType.In)); (with tut_Add being the GUIText) doesn't work either. What am I doing wrong?
(I don't know why Unity Answers is parsing http:// urls, I of course don't have those in the actual code.)