The (in my eyes) best way to control this is a Coroutine:
[Tooltip("Adjust how fast you want to move (units/second)")]
[SerilaizeField] private float moveSpeed;
[Tooltip("Fill this with your desired move steps")]
// via the INSPECTOR in Unity! (later changes here in code will have no effect!)
[SerializeField] private Vector3[] moveSteps = new []
{
Vector3.forwards * 500,
Vector3.left * 500,
Vector3.backwards * 500,
Vector3.right * 500
};
// Yes, this is possible!
// If start is an IEnumerator it is automatically started as Coroutine by Unity
private IEnumerator Start()
{
// This looks creepy but is fine in an
// IEnumerator as long as you yield somewhere within!
while(true)
{
// iterate through the array of movements
foreach(var step in moveSteps)
{
var currentTargetPosition = transform.position + step;
// This checks if the two positions match "exactly"
// If it is enough that the positions match up to a precision of 0.00001
// it would be more efficient to simply compare
//while(transform.position != currentTargetPosition)
while(!Mathf.Approximately(Vector3.Distance(transform.position, currentTargetPosition), 0f))
{
// move one step towards the current target position
// without overshooting
transform.position = Vector3.MoveTowards(transform.position, currentTargetPosition, moveSpeed * Time.deltaTime);
// Tells Unity to "pause" here, render this frame and
// continue from here in the next frame
yield return null;
}
// to be sure to reach sharp positions set the target fix
transform.position = currentTargetPosition;
}
}
}
This would move the object with a constant velocity of moveSpeed from one target position to the next using the configured moveStepsas pattern.
If you rather want to add some ease-in and -out towards the "edges" you could also do something like
private IEnumerator Start()
{
while(true)
{
foreach(var step in moveSteps)
{
var currentPosition = transform.position;
var currentTargetPosition = currentPosition + step;
// Get the expected move duration according to the speed
var duration = Vector3.Distance(transform.position, currentTargetPosition) / moveSpeed;
var timePassed = 0f;
while(timePassed < duration)
{
// Get a factor betwwen 0 and 1
var factor = timePassed / duration;
// add easing
factor = Mathf.SmoothStep(0, 1, factor);
// Interpolate the position between the start and endpoint
transform.position = Vector3.Lerp(currentPosition, currentTargetPosition, factor);
// increase by the time passed since last frame
timePassed += Time.deltaTime;
yield return null;
}
// to be sure to reach sharp positions set the target fix
transform.position = currentTargetPosition;
}
}
}