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。INTERMEDIATE_POINTS = 20
; (0,0,0),(20,0,0),(40,0,0),...,(960,0,0),(980,0,0),(1000,0,0)。速度相同,所用时间:t3。结果:t1< t3< 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
设置一个断点,用不同数量的中间点检查持续时间。
答案 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
,如果超过,您将始终转到下一个航路点。而不是试图在一个小窗口中放置对象,而只是确保对象已经通过或遇到了它的航路点。