Hello users, I’m here to kindly ask your help with two coroutines I made. When my game goes for Game Over, before showing the player the options of restart or menu, I wanted to make a curtain animation. So Game Over leads to curtain down, restart option pops up and curtain goes up again. Now…the weird part is I made two coroutines, one moving the courtine down and the second moving it up and it I call the, it goes down and doesn’t go all the way up.
void MovesDown()
{
StartCoroutine("CurtainDown");
}
IEnumerator CurtainDown()
{
float seconds = 0.01f;
float speed = 1.2f;
int value = 119;
for (int i = 0; i < value; i++)
{
cortina.transform.position = cortina.transform.position + new Vector3(0, -1 * speed * seconds, 0);
yield return null;
}
}
void MovesUp()
{
StartCoroutine("CurtainUp");
}
IEnumerator CurtainUp()
{
float seconds = 0.01f;
float speed = 1.25f;
float value = 237;
for (int i = 0; i < value; i++)
{
cortina.transform.position = cortina.transform.position + new Vector3(0, 1 * speed * seconds, 0);
yield return null;
}
}
I set different speed and values trying to handle that problem but there is also a second thing messing my code up. If the player stay alive for different durations of time, the curtain moving down(and up) also stops at different positions…I feel like I’m missing out something silly, do you guys have any idea ?
Switching for while only didn’t work but then I deleted the functions MoveDown and MoveUp and started calling directly the coroutines, maybe the void function was messing up with the floats ?
Edit: Also its not that much important since the moving speed isn’t that different but can you guys explain me why Vector3.Down and Vector3.Up moves differently ? I thought its supposed to be just (0,-1,0) and (0,1,0). Since the speed/seconds I set is fix, why do I have to put different numbers in the float value ?
Edit2: Nevermind, the curtain are going in different speeds again, I don’t know whats happening anymore lol.
You’re completely missing the point of doing any sort of movement in a game. A coroutine is no different from a function called in the Update method, except that it pauses until the next frame during “yield” statements.
You’re not scaling your movements with Time.deltaTime, thus your animation speed changes according to your framerate!
Changing
cortina.transform.position = cortina.transform.position + new Vector3(0, -1 * speed * seconds, 0);
to
cortina.transform.position = cortina.transform.position + new Vector3(0, -1 * speed * seconds, 0) * Time.deltaTime;
or
cortina.transform.position = cortina.transform.position + new Vector3(0, -1 * speed * seconds * Time.deltaTime, 0);
Also, I believe your approach is very weird and error prone. My recommandations:
Simply create an animator. Create a “curtain down” and a “curtain up” animation. They would only need 2 frames, the first and last frame, the animator will do the interpolation for you. Then you might need 2 additional “static” animations, that are simply the last frames of the previous animations, so the curtains stay in place. Its a very elegant and easy solution in my opinion.
Why calculate the position you need via a for loop with and index? Thats really unelegant code and if you ever look at it later you will likely be very confused. The code I would use:
IEnumerator CurtainDown()
{
float secondsForAnimationToFinish = 1.0f; //1 second
float currentAnimationTime = 0;
float xDistToMove = 5.0f; // Insert the distance you wish the curtain to move or change the axis
float oldX = cortina.transform.position.x;
float xAfterDone = oldX + xDistToMove;
while (currentAnimationTime < secondsForAnimationToFinish)
{
currentAnimationTime += Time.deltaTime;
// The time may very easily overshoot the exact time we want, so we need to break the interpolation cleanly
if (currentAnimationTime >= secondsForAnimationToFinish)
{
cortine.transform.position = new Vector3(xAfterDone,0,0);
yield break;
}
float normalizedTime = currentAnimationTime / secondsForAnimationToFinish; // Normalize time to be a number from 0-1
float distanceToMove = normalizedTime * xDistToMove; // This should interpolate the x value correctly for every frame
cortina.transform.position = new Vector3(oldX + distanceToMove,0,0);
yield return null;
}
}
This is untested code and will need some tweaking, but you should get the idea.
Yeah I figured out I made some bad choices there, right now I’m using MoveTowards and it’s way better. So far its working…Still figuring out how to make things properly and in a clean way. Also I belive the part you say that the time gets overshoot were my problem, since sometimes it stopped in the perfect spot or just moved a bit more and went all the way out of screen.