0
while (transform.position != new Vector3(desX, desY))
{
    // 2 - Movement
    Vector3 movement = new Vector3(
        0.1f * desX,
        0.1f * desY,
        0);

    //movement *= Time.deltaTime;
    transform.Translate(movement);
}    

This part of my program crashes the Unity engine and I'm pretty sure it's an infinite loop but I can't figure out why or how to fix it.

  • 1
    This may be an issue with float comparison, the values may not exactly equal what you are checking against. – Ron Beyer Aug 30 '18 at 03:45
  • @RonBeyer is right. What are you trying to do anyway? – kgbph Aug 30 '18 at 03:47
  • It looks like you are trying to move a gameobject towards a position. Take a look at https://docs.unity3d.com/ScriptReference/Vector3.MoveTowards.html – kgbph Aug 30 '18 at 03:49

2 Answers2

4

It's freezing your application because you're are not giving other scripts chance to run when the condition in the while loop is not met.

To fix that put that code in a coroutine function then add yield return null; to the while loop. This makes Unity to wait for a frame after each loop therefore given other scripts the opportunity to run every frame. This should fix the freeze issue whether the while loop exits or not. I would also suggest you use Vector3.Distance to determine when you are close to the destination.

public float reachThreshold = 0.2f;

void Start()
{
    StartCoroutine(MoveBject());
}

IEnumerator MoveBject()
{
    float distance = Vector3.Distance(transform.position, new Vector3(desX, desY));

    while (distance > reachThreshold)
    {
        // 2 - Movement
        Vector3 movement = new Vector3(
            0.1f * desX,
            0.1f * desY,
            0);

        //movement *= Time.deltaTime;
        transform.Translate(movement);

        //Wait a frame
        yield return null;
    }
}

If you really want to move GameObject to another position over time, see this post.

Programmer
  • 121,791
  • 22
  • 236
  • 328
3
  1. In general don't do things in while that are meant to happen in a per frame base! (Thanks Ron)
    The result of while in the best case would be that your App stucks until eventually the vectors match, making the object "jump" in position. In the worst case they never match and your App freezes forever.

    Instead you should use the Update() method, which is called each frame, and just move the object one step per frame.

  2. To compare the Vectors you should better use Vector3.Distance. Using the == operator for Vector3 is basically ok but internally it does something equal to

    Vector3.Distance(vectorA, vectorB) <= 0.00001f
    

    which uses a very small thershold that might not match exactly. So Using Vector3.Distance you can set your own threshold e.g. to 0.1 to make it "easier" to match.

     bool match = Vector3.Distance(transform.position, new Vector3(desX, desY) < 0.1f
    
  3. To move an object towards another Unity actually already has a built-in method Vector3.MoveTowards e.g.

    transform.position = Vector3.MoveTowards(transform.position, new Vector3 (desX, desY), 0.1f);
    

    This takes care of Vectors3 comparing so you don't even need it anymore.

  4. To make it smooth and framarate-save you were right already to use Time.deltaTime. Without this it would move 0.1 meters / frame but your framerate might not be stabil. Using Time.deltaTime makes it 0.1 meters / second which in almost all cases is what you actually want to achieve.

So to put it together your code should be something like

float desX;
float desY;

float moveSpeed = 0.1f;

void Update()
{
    var targetPosition = new Vector3 (desX, desY);

    transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
}

Note that in some cases MoveTowards still is not relayable enough e.g. if you want to track collisions or something. In this case refer here

derHugo
  • 83,094
  • 9
  • 75
  • 115
  • 4
    You should not be using a while loop to move things in unity, that is what the Update method is for. – Ron Beyer Aug 30 '18 at 03:55
  • 3
    1. `Vector3` can take 2 arguments. The third would be 0. This is made so that you create create `Vector3` from `Vector2`. 2.That's really irrelevant here. The OP is comparing `Vector3` not `float`. There is a built-in overload for comparing two Vectors. It is not comparing float but instead checking the difference of their magnitude . 3.You can use `while` loop for moving objects too. I don't know what else to say but this does not address the problem. It shows another way to do it as a solution but doesn't address the current issue. – PerformanceFreak Aug 30 '18 at 04:18
  • Additionally, floats are almost never equal (and vectors are composed of floats). Use `Mathf.Approximately` to compare them. – Draco18s no longer trusts SE Aug 30 '18 at 20:22
  • 1
    @Draco18s Usually yes but comparing `Vector3` using the [`==` operator](https://docs.unity3d.com/ScriptReference/Vector3-operator_eq.html) already uses approximation by internally doing something that compares to `Vector3.Distance(vectorA, vectorB, 0.00001)` so just using a very small threshold – derHugo Aug 31 '18 at 12:11