Reputation: 258
My coroutine to fade the player out after they die,
// Fade out ragdoll
IEnumerator RagdollFade()
{
yield return new WaitForSeconds(3f);
while (startingColour.a > 0.0f)
{
headSR.color = new Color(headSR.color.r, headSR.color.g, headSR.color.b, headSR.color.a - (Time.deltaTime / 1.5f));
bodySR.color = new Color(bodySR.color.r, bodySR.color.g, bodySR.color.b, bodySR.color.a - (Time.deltaTime / 1.5f));
leftArmSR.color = new Color(leftArmSR.color.r, leftArmSR.color.g, leftArmSR.color.b, leftArmSR.color.a - (Time.deltaTime / 1.5f));
rightArmSR.color = new Color(rightArmSR.color.r, rightArmSR.color.g, rightArmSR.color.b, rightArmSR.color.a - (Time.deltaTime / 1.5f));
leftLegSR.color = new Color(leftLegSR.color.r, leftLegSR.color.g, leftLegSR.color.b, leftLegSR.color.a - (Time.deltaTime / 1.5f));
rightLegSR.color = new Color(rightLegSR.color.r, rightLegSR.color.g, rightLegSR.color.b, rightLegSR.color.a - (Time.deltaTime / 1.5f));
yield return null;
}
}
speeds up after each execution.
For example, this first time the coroutine is called everything works fine and after 3 seconds the player is faded out. However, the next time it is called 3 seconds don't pass before the fade, the next time even less time, etc.
startingColour
is set in the Start() function.
Upvotes: 0
Views: 406
Reputation: 258
Ok, I've solved the problem, and it's completely my bad.
I realized that ANOTHER coroutine I had was interfering with the current one, so that's why StopCoroutine()
and adding a fade check wasn't working.
Sorry guys for not including that in my question post, you would probably have been able to help me out more effectively.
So for anyone who encounters strange routine behavior in the future, make sure two coroutines are not interfering with each other.
Upvotes: 1
Reputation: 46
Try call StopCoroutine()
before starting a new Coroutine. Possibly you have a few coroutines working at the same time.
Upvotes: 2
Reputation: 90724
It seems that your startingColour.a
value is always bigger then 0
so the while
loop never finishes and your coroutine just runs forever. Hard to tell without seeing the rest of your code.
So if you start it a second time you now have both routines running parallel => now each frame you decrease the alphas by the double amount .. then triple .. etc. and it also doesn't wait the 3 seconds before the first called routines are already running the while
loop so they continue to decrease the alphas.
You could use StopAllCoroutines
or StopCoroutine
in order to interrupt any still running routines when starting a new one. But that's actually more a kind of dirty workaround.
I would rather takle the actual issue and make sure your while loop returns which is currently unlikely to happen since you seem to not change startColor.a
anywhere.
Or add a flag not allowing parallel routines at all like e.g.
private bool isFading;
IEnumerator RagdollFade()
{
if(isFading) yield brake;
// prevents other routines
isFading = true;
...
// reset the flag once routine is finished
isFading = false;
}
Then I would also rather suggest to have one single float
value you use for fading using Color.Lerp
like
private bool isFading;
// you can also use a fixed duration and not pass it as parameter
// but this way you are even more flexible
IEnumerator RagdollFade(float duration)
{
if(isFading) yield brake;
// prevents other routines
isFading = true;
yield return new WaitForSeconds(3f);
// it is more performant to gather all required information beforehand
headStartColor = headSR.color;
bodyStartColor = bodySR.color;
leftArmStartColor = leftArmSR.color;
rightArmStartColor = rightArmSR.color;
leftLegStartColor = leftLegSR.color;
rightLegStartColor = rightLegSR.color;
headTargetColor = new Color(headStartColor.r, headStartColor.g, headStartColor.b, 0f);
bodyTargetColor = new Color(bodyStartColor.r, bodyStartColor.g, bodyStartColor.b, 0f);
leftArmTargetColor = new Color(leftArmStartColor.r, leftArmStartColor.g, leftArmStartColor.b, 0f);
rightArmTargetColor = new Color(rightArmStartColor.r, rightArmStartColor.g, rightArmStartColor.b, 0f);
leftLegTargetColor = new Color(leftLegStartColor.r, leftLegStartColor.g, leftLegStartColor.b, 0f);
rightLegTargetColor = new Color(rightLegStartColor.r, rightLegStartColor.g, rightLegStartColor.b, 0f);
var passedTime = 0f;
while (passedTime < duration)
{
// get the interpolation factor from 0 to 1
var factor = passedTime / duration;
// for adding additional ease-in and ease-out
// factor = Mathf.SmoothStep(0, 1, factor);
headSR.color = Color.Lerp(headStartColor, headTargetColor, factor);
bodySR.color = Color.Lerp(bodyStartColor, bodyTargetColor, factor);
leftArmSR.color = Color.Lerp(leftArmStartColor, leftArmTargetColor, factor);
rightArmSR.color = Color.Lerp(rightArmStartColor, rightArmTargetColor, factor);
leftLegSR.color = Color.Lerp(leftLegStartColor, leftLegTargetColor, factor);
rightLegSR.color = Color.Lerp(rightLegStartColor, rightLegTargetColor, factor);
// avoid overshooting
passedTime += Mathf.Min(Time.deltatime, duration - passedTime);
yield return null;
}
// reset the flag once routine is finished
isFading = false;
}
This is more flexible and you can add ease-in and ease-out using whatever simple math you like.
Upvotes: 4