Как передвинуть объект из точки А в точку B, и после того как он достиг точки подождать определенное время, и снова передвинуть

Как передвинуть объект из точки А в точку B, и после того как он достиг точки подождать определенное время, и снова передвинутся с точки B в новую точку.

Хочу что бы объект передвигался в точку после чего стоял на месте определенное время, и после снова перемещался в другую точку, не как не выходит понять, уже очень долго мучаюсь над этим. Помогите пожалуйста. Объект просто телепортируется по точкам. Нужно что - бы объект плавно дошел до точки назначения, ждал там некоторое время, и после снова перемещался

public class Coroutine : MonoBehaviour

{

// стартовая позиция
private Vector3 startPosition;
// новая позиция объекта
private Vector3 newPoint;

private void Start()
{
    // даю начальную позицию
    startPosition = transform.position;
}

private void Update()
{
    // указываю новую точку рандомными координатами, от начальной точки
    newPoint = new Vector3(
        Random.Range(startPosition.x - 5, startPosition.x + 5),
        startPosition.y,
        Random.Range(startPosition.z + 5, startPosition.z - 5)
        ); 
    // запускаю корутину
    StartCoroutine(MoveCoroutine(newPoint));
}

private IEnumerator MoveCoroutine(Vector3 moveTo)
{
    // жду 2 сек
    yield return new WaitForSeconds(2f);
    // если позиция объекта не равна конечной точки
    if (transform.position != newPoint)
    {
        // телепортирую объект по отрезку, создавая иллюзию перемещения
        transform.position = Vector3.Lerp(transform.position, newPoint, Time.time / 0.5f);
    }
}

}


Ответы (2 шт):

Автор решения: Yaroslav

С корутиной движение не будет плавной, поэтому Update.

Выделить передвижение и задержку в отдельные компетенции.

TimeAction и MoveAction можно использовать везде и на основе TimeAction, как с MoveAction можно написать ещё много самых разнообразных действий.

public class Test : MonoBehaviour {

    private void Start () {
        MoveToRandomPosition();
    }

    private void MoveToRandomPosition () {
        Vector3 NewPos = new Vector3(Random.Range(-5, 5), Random.Range(-5, 5), Random.Range(-5, 5));
        //gameObject.AddComponent<MoveAction>().MoveWithTime(1, NewPos, DelayRandomTime);
        gameObject.AddComponent<MoveAction>().MoveWithSpeed(3, NewPos, DelayRandomTime);
    }

    private void DelayRandomTime () {
        float DelayTime = Random.Range(0, 5);
        gameObject.AddComponent<TimeAction>().Delay(DelayTime, MoveToRandomPosition);
    }
}

public delegate void TimeActionFinish();

public class TimeAction : MonoBehaviour {
    protected float ActionTime, ActionTimer;
    protected TimeActionFinish Finish;

    public virtual void Delay (float time, TimeActionFinish finish) {
        ActionTimer = 0;
        ActionTime = time;
        Finish = finish;
    }

    private void Update () {
        ActionTimer += Time.deltaTime;
        float Way = ActionTimer/ActionTime;
        if (Way < 1)
            UpdateWay(Way);
        else {
            UpdateWay(1);
            if (Finish != null)
                Finish();
            Destroy(this);
        }
    }

    protected virtual void UpdateWay (float way) { }
}

public class MoveAction : TimeAction {
    private Vector3 _moveFrom, _moveTo;

    public void MoveWithTime (float time, Vector3 target, TimeActionFinish finish) {
        _moveFrom = gameObject.transform.localPosition;
        _moveTo = target;
        base.Delay(time, finish);
    }

    public void MoveWithSpeed (float speed, Vector3 target, TimeActionFinish finish) {
        MoveWithTime(Vector3.Distance(gameObject.transform.localPosition, target)/speed, target, finish);
    }

    protected override void UpdateWay (float way) {
        transform.localPosition = Vector3.Lerp(_moveFrom , _moveTo , way);
    }
}
→ Ссылка
Автор решения: Alteracia

Движение не плавное потому, что Lerp обрабатывается один раз в конце корутина. Правильней такое перемещение делать в Update, т.к. операция будет выполняться один раз за кадр. Если перемещаемый объект будет взаимодействовать с другими (физика), то перемещать его нужно иначе - через Velocity или Force и обрабатывать в FixedUpdate. В корутине можно сделать плавное движение, но это неправильно с точки зрения оптимизации. Нужно разбить существующий корутин на два:

public class Coroutine : MonoBehaviour
{
    // булин для таймера
    private bool moved;
    // булин для движения
    private bool time_out;
    // стартовая позиция
    private Vector3 startPosition;
    // новая позиция объекта
    private Vector3 newPoint;

    private void Start()
    {
        // даю начальную позицию
        startPosition = transform.position;
        time_out = false;
        moved = true;
    }

    private void Update()
    {
        // указываю новую точку рандомными координатами, от начальной точки
        newPoint = new Vector3(
            Random.Range(startPosition.x - 5, startPosition.x + 5),
            startPosition.y,
            Random.Range(startPosition.z + 5, startPosition.z - 5)
            );
        if (moved)
            StartCoroutine(Timer());
        // запускаю корутину
        if (time_out)
            StartCoroutine(MoveCoroutine(newPoint));
    }

    private IEnumerator Timer()
    {
        moved = false;
        // жду 2 сек
        yield return new WaitForSeconds(2f);
        time_out = true;
    }

    private IEnumerator MoveCoroutine(Vector3 moveTo)
    {
        time_out = false;
        // если позиция объекта не равна конечной точки
        if (Vector3.Distance(transform.position, moveTo) != float.Epsilon)
        {
            WaitForEndOfFrame wait = new WaitForEndOfFrame();
            // Двигаем объект пока он не передвинется на новую позицию
            do
            {
                // телепортирую объект по отрезку, создавая иллюзию перемещения
                transform.position = Vector3.Lerp(transform.position, moveTo, Time.deltaTime);
                // ждем до конца кадра
                yield return wait;
            } while (Vector3.Distance(transform.position, moveTo) < float.Epsilon);
        }
        moved = true;
    }
}
→ Ссылка