ScottishTapWater
ScottishTapWater

Reputation: 4806

How to move an object between two points in Unity?

I am attempting to translate a chess piece up, across and then back down using the lerp functionality of unity. However, whenever I trigger this script, the entire session freezes.

Using the unity debugger, I have narrowed the problem down to this section of code.

            do
        {
            float distCovered = (Time.time - startTime) * speed;
            fracJourney = distCovered / journeyLength;
            Debug.Log(fracJourney);
            transform.position = Vector3.Lerp(startPoint, endPoint, speed);
        } while (fracJourney <= 1);

because it would appear that none of the variables are altering and consequently, the entire loop is infinite.

Here is the entire section of code dedicated to handling the movement (the vector values are currently arbitrary).

    public class MovePiece : MonoBehaviour {
    Vector3 startPoint;
    Vector3 endPoint;
    float speed = 10;
    float startTime;
    private bool moving = false;
    private bool up = false;
    private bool across = false;
    private bool down = false;
    public void Start()
    {
        startPoint = gameObject.GetComponent<Transform>().position;
        startTime = Time.time;
        moving = true;
        Debug.Log("Moving Piece");
    }

    void Update() {
        if (!moving)
        {
            Destroy(this);
            return;
        }
        moveManager();
            }
    void moveManager()
    {
        if (!up)
        {
            lerpUp();
            return;
        }
        if (!across)
        {
            lerpAcross();
            return;
        }
        if (!down)
        {
            lerpDown();
            return;
        }
    }

    private void lerpUp()
    {
        Debug.Log("Upwards");
        startPoint = gameObject.GetComponent<Transform>().position;
        endPoint = startPoint + new Vector3(0, 0, 50);
        float journeyLength = Vector3.Distance(startPoint, endPoint);
        float fracJourney;
        do
        {
            float distCovered = (Time.time - startTime) * speed;
            fracJourney = distCovered / journeyLength;
            Debug.Log(fracJourney);
            transform.position = Vector3.Lerp(startPoint, endPoint, speed);
        } while (fracJourney <= 1);
        up = true;
        Debug.Log("Upwards Finished");
        return;
    }
    private void lerpAcross()
         {
             Debug.Log("Across");
             startPoint = gameObject.GetComponent<Transform>().position;
             endPoint = startPoint + new Vector3(0, 50, 0);
              float journeyLength = Vector3.Distance(startPoint, endPoint);
             float fracJourney;
             do
             {
                 float distCovered = (Time.time - startTime) * speed;
                 fracJourney = distCovered / journeyLength;
                 transform.position = Vector3.Lerp(startPoint, endPoint, speed);
             } while (fracJourney <= 1);
        across = true;
        Debug.Log("Across Finished");
        return;
         }
    private void lerpDown()
    {
        Debug.Log("Down");
        startPoint = gameObject.GetComponent<Transform>().position;
        endPoint = startPoint + new Vector3(0, 0, -50);
        float journeyLength = Vector3.Distance(startPoint, endPoint);
        float fracJourney;
        do
        {
            float distCovered = (Time.time - startTime) * speed;
            fracJourney = distCovered / journeyLength;
            transform.position = Vector3.Lerp(startPoint, endPoint, speed);
        } while (fracJourney <= 1);
        down = true;
        Debug.Log("Down Finished");
        moving = false;
        Debug.Log("Moving Finished");
        return;
    }

}
}

I have been trying for days to narrow this problem down, to no avail, so any help would be greatly appreciated.

Upvotes: 2

Views: 5084

Answers (2)

You've got more than one problem here.

The first is that you're using a loop inside your lerp functions. The game won't update the render output until the loop finishes. It doesn't matter if the loop is infinite or not, it's not going to execute only one iteration, it's going to do all of them (it also doesn't help that Time.time doesn't change during this process).

Second is that you're calculating the distance moved as an amount of distance from the start of the application not the start of the current move.

Third, you're calling Vector3.lerp() passing it a third parameter (the "float-percentage") with the value of speed not the fractional amount that should be calculated. e.g. Vector3.Lerp(startPoint, endPoint, 0.5f); will return the midpoint between startPoint and endPoint.

Fourth, there's no reason to have four methods for lerping your animation. You only need one, but you have to pass it the desired destination as well (rather than having four methods that imply different destinations).

Fifth, you're calculating journeyLength as the distance between the startPoint and the endPoint despite having previously calculated the endPoint as startPoint + distance (that's what new Vector3(0,0,50) is: a distance!)

Upvotes: 1

maraaaaaaaa
maraaaaaaaa

Reputation: 8163

do
    {
        float distCovered = (Time.time - startTime) * speed;
        fracJourney = distCovered / journeyLength;
        Debug.Log(fracJourney);
        transform.position = Vector3.Lerp(startPoint, endPoint, speed);
    } while (fracJourney <= 1);

Update() only runs once per frame, and Time only gets updated when it does, so Time will never change in the matter of one Update(), so (Time.time - startTime) * speed will always stay the same, so distCovered will never change, so fracJourney will never change, so fracJourney <= 1 will never change, so you are stuck in the loop forever.

If you are looking for a fix, you shouldnt need a while loop inside of an Update() function, almost ever. Use the Update() function itself as your loop, or use an IEnumerator where you can yield out and let a frame pass, as such:

public IEnumerator MyLoop()
{
    while (fracJourney <= 1)
    {
        float distCovered = (Time.time - startTime) * speed;
        fracJourney = distCovered / journeyLength;
        Debug.Log(fracJourney);
        transform.position = Vector3.Lerp(startPoint, endPoint, speed);

        yield return null;     //< --- yield out and let a frame pass
    }
}

Upvotes: 1

Related Questions