Как мне переместить объект в место назначения, которое сохраняется при щелчке мыши?

Я пытаюсь добиться самого простого. У меня есть код для плавного перемещения объекта, и я хочу, чтобы он останавливался на определенном расстоянии относительно того, где находился объект при нажатии кнопки. Поэтому я не могу сохранить позицию внутри любой функции, которая обновляет каждый кадр. Сейчас объект просто начинает двигаться и не останавливается.

void Update()
    {
        Vector3 targetPosition = new Vector3(transform.position.x - 1, transform.position.y, transform.position.z);

        if (movement == true)
        {
            float step = speed * Time.deltaTime;
            transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
        }
    }

    public void coroutineStarter()
    {
        float targetPosition = transform.position.x - 1;
        StartCoroutine(OnClick(targetPosition));
    }



    IEnumerator OnClick(float targetPosition)
    {
        if (transform.position.x != targetPosition)
        {
            movement = true;
        }
        else
        {
            movement = false;
            yield return null;
        }
    }
}

Я должен указать, что нажатие на кнопку запускает coroutineStarter. Я попытался использовать цикл while вместо оператора if внутри OnClick, но, по-видимому, использование циклов while в любом месте замораживает единство, если оно бесконечно, а если нет, оно замораживает единство на время цикла.


person MongolianShaman    schedule 22.11.2019    source источник
comment
он не замораживает Unity, если вы yield return null; в нем .. что говорит Unity приостановить процедуру, отрендерить кадр и продолжить в следующем кадре.   -  person derHugo    schedule 22.11.2019


Ответы (1)


Я бы не стал путать Coroutine с кодом, работающим в Update. Coroutine уже похож на временный Update метод, так что вы можете просто сделать

public void coroutineStarter()
{
    var targetPosition = transform.position + Vector3.left;
    StartCoroutine(OnClick(targetPosition));
}

IEnumerator OnClick(Vector3 targetPosition)
{
    while (transform.position.x != targetPosition)
    {
        float step = speed * Time.deltaTime;
        transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);

        // Important! Tells Unity to pause here, render this frame
        // and continue from here in the next frame
        yield return null;
    }

    // When done set the position fixed once
    // since == has a precision of 0.00001 so it never reaches an exact position
    transform.position = targetPosition;
}

Это перемещает объект в заданное положение с постоянной скоростью.


Немного другой подход - перемещение объекта за определенное время, но он позволяет добавить легкость входа и выхода в начале и в конце движения с помощью Vector3.Lerp и SmoothStep

IEnumerator OnClick(Vector3 targetPosition)
{
    var startPosition = transform.position;
    var distance = Vector3.Distance(startPosition, targetPosition);

    if(distance <= 0) yield break;

    var duration = distance / speed;
    var timePassed = 0f;

    while (timePassed < duration)
    {
        var factor = timePassed / duration;
        // Optionally add easing
        factor = Mathf.SmoothStep(0,1,factor);

        transform.position = Vector3.Lerp(startPosition, targetPosition, factor);

        // increase by time since last frame avoiding overshooting
        timePassed += Mathf.Min(Time.deltaTime, duration - timePassed);

        // Important! Tells Unity to pause here, render this frame
        // and continue from here in the next frame
        yield return null;
    }

    // When done set the position fixed once
    // this time just in case you never know ;)
    transform.position = targetPosition;
}
person derHugo    schedule 22.11.2019