2
\$\begingroup\$

I am using this script below to move an animated object in unity with no root-motion. it simply walks across the terrain and has a timer so it waits 60 seconds until starting.

void Update ()
{
    if (Time.timeSinceLevelLoad > 60)
    {
        transform.Translate(0, 0, Time.deltaTime);
    }
}

I want the object to travel a certain distance or certain amount of steps and then stop at an exact point and stay there, is there a simple way to add to the above code to do this? does it entail xyz position reached maybe?

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Did you look at the Vector3.MoveTowards method? It handles exactly this case. \$\endgroup\$
    – DMGregory
    Commented Mar 29, 2019 at 19:28

2 Answers 2

4
\$\begingroup\$

We can do this more simply:

public class WaitThenMoveToTarget : MonoBehaviour {

    // Set your parameters in the Inspector.
    public float waitSeconds = 60f;
    public Vector3 targetOffset = Vector3.forward * 10f;
    public float speed = 1f;

    // Make Start a coroutine that begins 
    // as soon as our object is enabled.
    IEnumerator Start() {

         // First, wait our defined duration.
         yield return new WaitForSeconds(waitSeconds);

         // Then, pick our destination point offset from our current location.
         Vector3 targetPosition = transform.position + targetOffset;

         // Loop until we're within Unity's vector tolerance of our target.
         while(transform.position != targetPosition) {

              // Move one step toward the target at our given speed.
              transform.position = Vector3.MoveTowards(
                    transform.position,
                    targetPosition,
                    speed * Time.deltaTime
               );

               // Wait one frame then resume the loop.
               yield return null;
         }

         // We have arrived. Ensure we hit it exactly.
         transform.position = targetPosition;
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ excuse the long delay, but have just got back to this now. The above code works very well for me (an 'i' missing in transform.position). Many thanks \$\endgroup\$
    – patrick
    Commented Apr 24, 2019 at 23:16
  • \$\begingroup\$ Thanks for the spellcheck! Fixed. :) Glad it worked for your needs. \$\endgroup\$
    – DMGregory
    Commented Apr 25, 2019 at 1:01
0
\$\begingroup\$

First you will want to define a start and end position in your scene. Create GameObjects in the editor to place at the start and end positions of your movement path, and drag and drop them into the startObject and endObject fields in the script below.

Then you can interpolate between the two positions using the Vector3.Lerp() function (more details here).

The code below linearly moves your object from startPos to endPos over moveDuration seconds.

public Transform startObject;
public Transform endObject;

[Tooltip("How long the movement will take in seconds.")]
public float moveDuration = 1;

[Tooltip("The delay in seconds before movement starts.")]
public float startDelay = 60;

bool isMoving = false;
bool hasMoved = false;



void Update() {
    // if it is time to move, and this object is not moving, and hasn't moved yet
    if (Time.timeSinceLevelLoad > startDelay && !isMoving && !hasMoved) {
        // start moving (this moves the current object from startObject.position to endObject.position over moveDuration seconds)
        StartCoroutine(Move(startObject.position, endObject.position, moveDuration));
    }
}


IEnumerator Move(Vector3 startPos, Vector3 endPos, float duration){
    // Record that we are about to start moving
    isMoving = true;
    // timeElapsed will incresase from 0 to duration over the course of the while loop
    var timeElapsed = 0f;
    while(timeElapsed < duration){
        // lerp (linearly interpolate) the position of this object between startPos and endPos
        // Use (timeElapsed / duration) to control how close it is to the startPos vs the endPos
        transform.position = Vector3.Lerp(startPos, endPos, timeElapsed/duration);
        // Wait a frame and record that time has elapsed 
        yield return new WaitForEndOfFrame();
        timeElapsed += Time.deltaTime;
    }    
    // Make sure that the object ends at the correct endPos
    transform.position = Vector3.Lerp(startPos, endPos, timeElapsed/duration);
    // Record that we are not moving anymore and that this object has moved
    isMoving = false;
    hasMoved = true;
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .