I'm using a coroutine to make a GameObject move from a random point A to a random point B. The GameObject should move along this trajectory at fixed intervals and at a constant speed.

However, each time my coroutine that executes the movement is called, the GameObject is a little bit faster.

private IEnumerator movement () {

        // Initialize position and rotation
        float distanceX = endTransform.position.x - startTransform.position.x;
        float distanceZ = endTransform.position.z - startTransform.position.z;
        float angleAroundY = 90.0f - Mathf.Rad2Deg*(Mathf.Atan2 (distanceZ, distanceX));

        this.gameObject.transform.position = startTransform.position;
        this.gameObject.transform.rotation = startTransform.rotation * Quaternion.Euler (90.0f, angleAroundY, 0.0f);

        // Move from point A to point B
        while (this.gameObject.transform != endTransform.transform) {
            float step = speed * Time.fixedDeltaTime;
            this.gameObject.transform.position = Vector3.MoveTowards (this.gameObject.transform.position, endTransform.transform.position, step);
            yield return null;
        yield return null;

I checked and the step variable is constant.

  • 2
    \$\begingroup\$ Where and how do you set your speed? I cannot see this part of the code being faulty if step is really constant. Though, maybe you are incrementing the speed once you initialize the movement... The one thing I'm unsure of here is your while condition, are you sure it ever finishes? The transforms might never be hitting your !=. I'm actually sure they will never be the same, but for the sake of this not being my code, I'll keep the "might" intact. That could cause make the coroutine never stop and upon your next start of movement, firing the coroutine twice. \$\endgroup\$ Feb 15, 2017 at 15:39
  • \$\begingroup\$ speed is a public variable of the class containing this coroutine. But since step` is constant each frame, speed must be constant too (and it is, I checked with log). I'll check if the transform actually hit the !=. \$\endgroup\$
    – user87553
    Feb 15, 2017 at 15:41
  • \$\begingroup\$ Okay, I edited the comment. Make sure the coroutine actually finishes. \$\endgroup\$ Feb 15, 2017 at 15:43
  • 1
    \$\begingroup\$ You were right, the issue was the fact that i checked if the transforms were the same, while I should have checked if the positions are the same. this.gameObject.transform and endTransform.transform had different rotations. \$\endgroup\$
    – user87553
    Feb 15, 2017 at 15:49
  • 1
    \$\begingroup\$ Heads-up, you don't want to use fixedDeltaTime here. That gives you the duration of a physics/FixedUpdate step, but this isn't running in the physics/FixedUpdate step: yield return null means it resumes with the next Update step. You want Time.deltaTime here, and in fact it's generally safe to always use Time.deltaTime when you want to know how much time this run of the script is accounting for - if you try to read this version during a FixedUpdate step, Unity will return the fixedDeltaTime for you automatically. \$\endgroup\$
    – DMGregory
    Feb 16, 2017 at 3:34

1 Answer 1


Turned my comment into answer, to make the question answered.

The problem lies in the while loop never actually reaching it's condition.

Only the position is being manipulated but whole transform equality is being tested and the rotations do not match, obviously.

That in return never stops the coroutine and whenever the coroutine is called again, the position is going to be reset and now both of the coroutines are going to execute their MoveTowards code. Order to move once more, and it's happening thrice... On and on and on..

The movement seemingly stops, because MoveTowards will equal the target if it was going to overshoot. This can make one think, that the coroutine has finished.

It's a simple fix - check explicitly for positions:

while (this.gameObject.transform.position != endTransform.position)
    // MoveTowards

You must log in to answer this question.