【问题标题】:How to move an object between two points in Unity?如何在 Unity 中的两点之间移动对象?
【发布时间】:2015-12-02 21:02:07
【问题描述】:

我正在尝试使用统一的lerp 功能将棋子向上、横向和向后平移。但是,每当我触发此脚本时,整个会话都会冻结。

使用统一调试器,我已将问题缩小到这部分代码。

            do
        {
            float distCovered = (Time.time - startTime) * speed;
            fracJourney = distCovered / journeyLength;
            Debug.Log(fracJourney);
            transform.position = Vector3.Lerp(startPoint, endPoint, speed);
        } while (fracJourney <= 1);

因为看起来没有任何变量在改变,因此整个循环是无限的。

这是专门用于处理运动的整个代码部分(矢量值目前是任意的)。

    public class MovePiece : MonoBehaviour {
    Vector3 startPoint;
    Vector3 endPoint;
    float speed = 10;
    float startTime;
    private bool moving = false;
    private bool up = false;
    private bool across = false;
    private bool down = false;
    public void Start()
    {
        startPoint = gameObject.GetComponent<Transform>().position;
        startTime = Time.time;
        moving = true;
        Debug.Log("Moving Piece");
    }

    void Update() {
        if (!moving)
        {
            Destroy(this);
            return;
        }
        moveManager();
            }
    void moveManager()
    {
        if (!up)
        {
            lerpUp();
            return;
        }
        if (!across)
        {
            lerpAcross();
            return;
        }
        if (!down)
        {
            lerpDown();
            return;
        }
    }

    private void lerpUp()
    {
        Debug.Log("Upwards");
        startPoint = gameObject.GetComponent<Transform>().position;
        endPoint = startPoint + new Vector3(0, 0, 50);
        float journeyLength = Vector3.Distance(startPoint, endPoint);
        float fracJourney;
        do
        {
            float distCovered = (Time.time - startTime) * speed;
            fracJourney = distCovered / journeyLength;
            Debug.Log(fracJourney);
            transform.position = Vector3.Lerp(startPoint, endPoint, speed);
        } while (fracJourney <= 1);
        up = true;
        Debug.Log("Upwards Finished");
        return;
    }
    private void lerpAcross()
         {
             Debug.Log("Across");
             startPoint = gameObject.GetComponent<Transform>().position;
             endPoint = startPoint + new Vector3(0, 50, 0);
              float journeyLength = Vector3.Distance(startPoint, endPoint);
             float fracJourney;
             do
             {
                 float distCovered = (Time.time - startTime) * speed;
                 fracJourney = distCovered / journeyLength;
                 transform.position = Vector3.Lerp(startPoint, endPoint, speed);
             } while (fracJourney <= 1);
        across = true;
        Debug.Log("Across Finished");
        return;
         }
    private void lerpDown()
    {
        Debug.Log("Down");
        startPoint = gameObject.GetComponent<Transform>().position;
        endPoint = startPoint + new Vector3(0, 0, -50);
        float journeyLength = Vector3.Distance(startPoint, endPoint);
        float fracJourney;
        do
        {
            float distCovered = (Time.time - startTime) * speed;
            fracJourney = distCovered / journeyLength;
            transform.position = Vector3.Lerp(startPoint, endPoint, speed);
        } while (fracJourney <= 1);
        down = true;
        Debug.Log("Down Finished");
        moving = false;
        Debug.Log("Moving Finished");
        return;
    }

}
}

我已经尝试了几天来缩小这个问题的范围,但无济于事,所以任何帮助都将不胜感激。

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:
    do
        {
            float distCovered = (Time.time - startTime) * speed;
            fracJourney = distCovered / journeyLength;
            Debug.Log(fracJourney);
            transform.position = Vector3.Lerp(startPoint, endPoint, speed);
        } while (fracJourney <= 1);
    

    Update() 每帧只运行一次,而Time 只在它运行时更新,所以Time 永远不会改变一个Update(),所以(Time.time - startTime) * speed 将永远保持不变,所以distCovered 永远不会改变,所以fracJourney 永远不会改变,所以fracJourney &lt;= 1 永远不会改变,所以你永远被困在循环中。

    如果您正在寻找解决方法,您几乎永远不需要在 Update() 函数内使用 while 循环。使用 Update() 函数本身作为您的循环,或使用 IEnumerator 在那里您可以让出并让帧通过,如下所示:

    public IEnumerator MyLoop()
    {
        while (fracJourney <= 1)
        {
            float distCovered = (Time.time - startTime) * speed;
            fracJourney = distCovered / journeyLength;
            Debug.Log(fracJourney);
            transform.position = Vector3.Lerp(startPoint, endPoint, speed);
    
            yield return null;     //< --- yield out and let a frame pass
        }
    }
    

    【讨论】:

    • 我对 c# 比较陌生,所以我会看看 IEnumeratoryield 但是,do 循环本身不在 Update() 例程中。它位于Update() 调用的子例程中,除非在这种情况下本质上算作相同的事情。
    • 它确实算作同一件事
    • 嗯,好的,现在可以使用了。是的,我现在明白为什么我的代码简直令人震惊
    【解决方案2】:

    这里有不止一个问题。

    首先是您在 lerp 函数中使用了循环。在循环结束之前,游戏不会更新渲染输出。循环是否无限无关紧要,它不会只执行一次迭代,它将完成所有(在此过程中Time.time 不会改变也无济于事)。

    其次,您将移动的距离计算为距离应用程序开始而不是当前移动开始的距离。

    第三,您调用 Vector3.lerp() 并传递第三个参数(“float-percentage”),其值为speed,而不是应计算的小数。例如Vector3.Lerp(startPoint, endPoint, 0.5f); 将返回 startPointendPoint 之间的中点。

    第四,没有理由使用 四种 方法来处理动画。您只需要一个,但您还必须将所需的目的地传递给它(而不是有四种方法暗示不同的目的地)。

    第五,您将journeyLength 计算为startPointendPoint 之间的距离,尽管之前已将endPoint 计算为startPoint + distance(这就是new Vector3(0,0,50) 的含义:距离!)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-02
      相关资源
      最近更新 更多