- Home /
[SOLVED] Coroutine while loop exits before condition met
I'm at a loss as to why my coroutine doesn't seem to be working. I'm trying to use MoveTowards to do a smooth translation of my character game object from one hex on the board to the next. I also tried Lerp with the same results. Here's the code:
private IEnumerator Walk()
{
fracDist = Vector3.Distance(transform.position, destination.transform.position);
while (fracDist > 0.01f)
{
Debug.Log("HexUnit.Walk: Before distance = " + fracDist.ToString()
+ "\n");
Vector3.MoveTowards(transform.position, destination.transform.position, Time.deltaTime * 1f);
fracDist = Vector3.Distance(transform.position, destination.transform.position);
Debug.Log("HexUnit.Walk: After distance = " + fracDist.ToString()
+ "\n");
yield return null;
}
}
And here's how I call it:
public void MoveUnit()
{
princeAnimator.SetBool("moving", true);
Debug.Log("HexUnit.MoveUnit: Starting to move\n");
StartCoroutine(Walk());
Debug.Log("HexUnit.MoveUnit: Done moving\n");
HaltUnit();
Location = destination;
}
The debug messages are as follows with identical timestamps:
HexUnit.MoveUnit: Starting to move
HexUnit.Walk: Before distance = 17.32051
HexUnit.Walk: After distance = 17.32051
HexUnit.MoveUnit: Done moving
HexUnit.Walk: Before distance = 17.32051
HexUnit.Walk: After distance = 0
HaltUnit() just tells the animator SetBool to go back to false. When I comment out the "Location = destination;" line, I just get non-stop pairs of Before and After distance debug lines reflecting 17.32051. What am I doing wrong either in the while loop or in the MoveUnit() method where I call the coroutine? Thanks in advance.
Answer by Llama_w_2Ls · Jan 23, 2021 at 10:11 AM
Coroutines outlive the function that is calling them. This means that any code after the line StartCoroutine(Walk());
immediately runs, regardless of whether the coroutine has finished or not. You should call HaltUnit()
in the coroutine, once the while loop has ended, because that's when the player has reached its target. @Gone2Plaid
Right, in addition I should note that the coroutine will never finish because the $$anonymous$$oveTowards line does nothing. $$anonymous$$oveTowards returns the new position. It can not modify the passed in Vector3. Since the return value is simply ignored the line is pointless. If you want to more the object this scirpt is attached to, you have to do:
transform.position = Vector3.$$anonymous$$oveTowards(transform.position, destination.transform.position, Time.deltaTime * 1f);
@Llama_w_2Ls - Thank you so much! The fact that the calling method continues past the coroutine call was what I didn't have my head around.
@Bunny83 - Thanks for the re$$anonymous$$der! I originally had my code exactly as you corrected it, but in my troubleshooting, I had left it incorrect. You saved me a lot of additional frustration.
In addition to Bunny83's correction, I moved the following up to the coroutine after the while loop, and that solved it!
HaltUnit();
Location = destination;
Solution accepted and upvotes applied. THANK YOU BOTH!