来源,目标和中间路点

时间:2015-01-26 13:21:40

标签: c# time unity3d distance

  1. 考虑两点:(0,0,0)作为源,(1000,0,0)作为目标
  2. 立方体游戏对象希望以预定义/恒定速度从源和目标移动。所用时间:t1
  3. 在源和目标之间引入100个中间点,即INTERMEDIATE_POINTS = 10 示例:(0,0,0),(10,0,0),(20,0,0),(30,0,0)....(980,0,0),(990) ,0,0),(1000,0,0)。速度相同,所用时间:t2。
  4. 引入50个<​​strong>中间点,即INTERMEDIATE_POINTS = 20; (0,0,0),(20,0,0),(40,0,0),...,(960,0,0),(980,0,0),(1000,0,0)。速度相同,所用时间:t3。
  5. 结果:t1&lt; t3&lt; t2,即更多中间点,到达目标所需的时间更多(尽管路径相同且速度相同)

    问题:如果比较,游戏对象在所有三种情况下(相同路径,相同速度)移动(没有中间体,100种中间体和50种中间体)以上。但为什么达到目标会有时差?

    测试此方案的代码:

    using UnityEngine;
    using System.Collections.Generic;
    
    public class TestSpeed : MonoBehaviour
    {
        private List<Vector3> listOfPoints = new List<Vector3>();
        private int INTERMEDIATE_POINTS = 1;
    
        private int counter = 1;
    
        private float speed = 50.0f;
    
        private float originalDistance = 0.0f;
        private float distanceCovered = 0.0f;
        private float overshoot = 0.0f;
        private Vector3 modifiedTarget;
    
        // for the car movement. 
        private Vector3 targetPosition; // after every loop, get the next position
        private Vector3 currentPosition;
    
        // Use this for initialization
        void Start()
        {
            for (int i = 0; i <= 1000; i = i + INTERMEDIATE_POINTS)
            {
                listOfPoints.Add(new Vector3(i, 0, 0));
            }
    
            currentPosition = this.transform.position; // at the beginning, from (0,0,0) 
            targetPosition = listOfPoints[counter];
    
        }
    
        // Update is called once per frame
        void Update()
        {
            originalDistance = Vector3.Distance(targetPosition, currentPosition);
            distanceCovered = Vector3.Distance(transform.position, currentPosition);
    
            if(Vector3.Distance(transform.position, new Vector3(0,0,0)) >= 995.0f)
            {
                System.TimeSpan t = System.TimeSpan.FromSeconds(Time.timeSinceLevelLoad);
                string answer = string.Format("{0:D2}:{1:D2}:{2:D2}",
                        t.Hours,
                        t.Minutes,
                        t.Seconds);
            }
    
            if ((originalDistance - distanceCovered) <= 0.0f)
            {
                currentPosition = transform.position;
                targetPosition = listOfPoints[counter];
                counter++;
            }
            else
            {
                float step = speed * Time.deltaTime;
                if((distanceCovered + step) >= originalDistance)
                {
                    overshoot = distanceCovered + step - originalDistance;
                    counter++;
                    modifiedTarget = Vector3.Lerp(targetPosition, listOfPoints[counter], (overshoot / originalDistance));
                }
                else
                {
                    modifiedTarget = targetPosition;
                }
    
                transform.position = Vector3.MoveTowards(transform.position, modifiedTarget, step);
            }
        }
    }
    

    如何使用代码:

    只需创建一个立方体游戏对象并将脚本分配给它。接近string answer设置一个断点,用不同数量的中间点检查持续时间。

1 个答案:

答案 0 :(得分:0)

我很确定这里的逻辑是奇怪观察的原因:

if ((originalDistance - distanceCovered) == 0.0f)
{
    currentPosition = transform.position;
    targetPosition = listOfPoints[counter];
    counter++;
}

通过检查完全位置匹配,检查您是否到达目的地航点;但是,每Update旅行的距离不算精确。这意味着您的对象可能超越目标,然后尝试向后移动,再次超越它,然后重复。

我敢打赌,如果你在场景视图中观察你的立方体,你会看到它在一个航点上徘徊一段时间,直到它设法达到所需的确切距离。

你最好在这里使用不等式,例如:

if ((originalDistance - distanceCovered) <= 0.0f)
{ /* ... */ }

如果物体行进的距离大于或等于行进所需的距离,则物体已达到其航点。一旦物体到达或经过航路点,originalDistance - distanceCovered将为负。

编辑:

X.....X.....X.....X.....X.....X

以下是一些航路点。假装我们有一个沿着航路点路径行进的物体。它从左边的第一个开始向右走。它将由O表示。

O.....X.....X.....X.....X.....X

现在它移动了一段时间。由于Time.deltaTime的可变性,它可能会在每个刻度上移动一个或两个点。所以,让我们说它在几个滴答之后结束了:

X....OX.....X.....X.....X.....X

在下一次打勾期间,它会移动两个:

X.....XO....X.....X.....X.....X

使用原始支票,对象现在将向后。它需要行驶7个车位的距离,但它行驶了8个。所以使用原始支票originalDistance - distanceCovered != 0.0f。所以它会不断尝试一遍又一遍地击中那个位置,直到它在点上击中它。

即使你引入了“门槛”的想法,你仍然会遇到同样的问题。每个蜱没有固定的行程距离,因此这意味着每个航路点都会有一些人为的“反弹”时间,除非该阈值太大以至于航路点变得毫无意义。

如果您使用originalDistance - distanceCovered <= 0.0f,如果超过,您将始终转到下一个航路点。而不是试图在一个小窗口中放置对象,而只是确保对象已经通过或遇到了它的航路点。