【问题标题】:How do I move an object to a destination that is stored on mouse click?如何将对象移动到通过鼠标单击存储的目标?
【发布时间】:2020-03-18 15:31:17
【问题描述】:

我正在努力实现最简单的事情。我有平滑移动对象的代码,并且我希望它停止在与单击按钮时对象所在位置相关的特定距离处。所以我不能将位置存储在任何更新每一帧的函数中。目前,对象只是开始移动并且不会停止。

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 循环而不是 OnClick 中的 if 语句,但显然在任何地方使用 while 循环都会冻结统一,如果它是无限的,如果不是,它会在循环期间冻结统一。

【问题讨论】:

  • 如果你在其中yield return null;,它不会冻结 Unity .. 这会告诉 Unity 暂停例程,渲染帧并在下一帧继续。

标签: c# loops unity3d coroutine


【解决方案1】:

我不会将 Coroutine 与在 Update 中运行的代码混为一谈。协程已经像一个临时的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.LerpSmoothStep在移动的开始和结束时添加缓入和缓出

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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多