- Home /
The question is answered, right answer was accepted
How can i make the for-loop only run a command once
First of all, I'd like to apologize if my English isn't very good but I'll try my best to make it easy to understand. I'm making a 2D game where the player controls some tiles on a grid by using some movement cards that tell where the cards are going to go. I want the card to move 1 unit every x seconds (where to depends on the card), so in order to achieve that I tried using an IEnumerator with a for loop inside (I only put code on the "Up" part to check if everything was working as intended):
IEnumerator AplicarMovimento()
{
for (int i = 0; i < Peças.Length; i++)
{
if (Peças[i] == "Up")
{
transform.position = new Vector2(transform.position.x, transform.position.y + 1);
}
else if (Peças[i] == "Down")
{
}
else if (Peças[i] == "Left")
{
}
else if (Peças[i] == "Right")
{
}
yield return new WaitForSeconds(TimeStep);
}
canMove = false;
}
The problem that I have is that the for loop is applying the vector while the TimeStep doesn't reach its destined time, and what I wanted was it applies the vector ONCE and then waits the x seconds (TimeStep), and then it would go into the next "i" in the for-loop. Is there any way to achieve that? Am I missing something? Any help would be appreciated. Thank you for your time!
you can exit a loop using break or return, break will exit the loop and return will exit the function.
Answer by unity_UD6vlOEW25WWeA · Jan 20, 2021 at 04:22 PM
Make sure that you are starting the function using: StartCoroutine("AplicarMovimento");
Hi, thanks for your answer! Yes I currently call the function on my update function, it's called every time the bool "can$$anonymous$$ove" = true and when the bool "can$$anonymous$$ove" = false it stops the courotine
Did you read the answer that logicandchaos kindly posted?
you can exit a loop using break or return, break will exit the loop and return will exit the function.
Wait, did you just say that you start a new coroutine every Update? That means you're running several coroutines in parallel. I think your overall concept is flawed. You should start the coroutine once. Coroutines are running "on their own" once started. So I guess since you talk about movement cards that the player is actually arranging, queueing those cards and when done they somehow start the movement sequence. All you have to do is start the coroutine from that point, once. People usually use something like your can$$anonymous$$ove flag to prevent the starting of a new coroutine while one is still running. However for that you would need to set can$$anonymous$$ove to false at the beginning and set it back to true at the end. However since we have no idea how and where you start your coroutine it's pointless to talk about potential fixes as this missing part is most likely where your issue is located.
This is currently where the couroutine starts, for now im using keyboard keys but latere on ill be using a button to start the whole thing:
private void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
can$$anonymous$$ove = true;
}
if (Input.GetKeyDown(KeyCode.L))
{
can$$anonymous$$ove = false;
}
if (can$$anonymous$$ove)
{
StartCoroutine(Aplicar$$anonymous$$ovimento());
}else { StopCoroutine(Aplicar$$anonymous$$ovimento()); }
}
IEnumerator Aplicar$$anonymous$$ovimento()
{
for (int i = 0; i < Peças.Length; i++)
{
if (Peças[i] == "Up")
{
transform.position = new Vector2(transform.position.x, transform.position.y + 1);
}
else if (Peças[i] == "Down")
{
}
else if (Peças[i] == "Left")
{
}
else if (Peças[i] == "Right")
{
}
yield return new WaitForSeconds(TimeStep);
}
can$$anonymous$$ove = false;
}
I've tried using break and return but those don't really fix the problem
why not just use a break; after it runs once or could run a while loop?
As you stated here The problem that I have is that the for loop is applying the vector while the Timestep doesn't reach its destined time,
the reason this is happening is that it is instantiated in void update which runs and gets called every frame so its not allowing the loop to fully run before it is called again so why not run it in a late or even fixed update?