C# 如何在给定的时间内移动射弹穿过各个位置,而不考虑位置计数
我想在某个特定的时间内,通过一系列的位置来引导一个投射物 我的代码在位置计数不是很高时起作用,但是当列表包含1000个点时,,投射所花费的时间不一样,它明显增加 我移动射弹的代码如下:C# 如何在给定的时间内移动射弹穿过各个位置,而不考虑位置计数,c#,unity3d,C#,Unity3d,我想在某个特定的时间内,通过一系列的位置来引导一个投射物 我的代码在位置计数不是很高时起作用,但是当列表包含1000个点时,,投射所花费的时间不一样,它明显增加 我移动射弹的代码如下: public float timeToMove = 3; public GameObject projectile; public ParabolaDrawer parabolaDrawer; //this class generates the list of the points private int c
public float timeToMove = 3;
public GameObject projectile;
public ParabolaDrawer parabolaDrawer; //this class generates the list of the points
private int currentPosIndex = 0;
private Vector3 currentPos = new Vector3();
private List<Vector3> parabolaPointsPositions = new List<Vector3>();
private bool hasArrivedToPos = false;
private bool hasArrivedToLastPos = false;
[ContextMenu("LaunchProjectile")]
private void LaunchProjectile()
{
currentPosIndex = 0;
hasArrivedToPos = false;
hasArrivedToLastPos = false;
parabolaPointsPositions = parabolaDrawer.parabolaPoints; //returns a List<Vector3>
projectile.transform.position = parabolaDrawer.parabolaPoints.ElementAt(0);
currentPos = projectile.transform.position;
StartCoroutine(MoveProjectileThroughTheParabola(timeToMove));
}
private IEnumerator MoveProjectileThroughTheParabola(float timeToMove)
{
float timeToMoveToNextPosition = timeToMove / (parabolaPointsPositions.Count - 1);
float step = 0f;
Vector3 initialPos = parabolaDrawer.initialPosition;
while (step < 1 && !hasArrivedToLastPos)
{
// Move our position a step closer to the target.
step += Time.smoothDeltaTime / timeToMoveToNextPosition; // calculate step distance to move in stablished time
projectile.transform.position = Vector3.Lerp(initialPos, currentPos, step);
//Check if arrived to the point
if (Vector3.Distance(projectile.transform.position, currentPos) <= 0.001f)
hasArrivedToPos = true;
if (hasArrivedToPos)
{
//Check which is the next point or if has arrived to the last one
if (currentPosIndex == (parabolaPointsPositions.Count - 1))
hasArrivedToLastPos = true;
else
{
initialPos = currentPos;
step = 0f;
currentPosIndex++;
currentPos = parabolaPointsPositions.ElementAt(currentPosIndex);
hasArrivedToPos = false;
}
}
yield return null;
}
}
Edit2:使用@NS1评论中的信息不断改进
private IEnumerator通过Parabola移动项目(浮动时间移动)
{
Vector3[]点=抛物线抽屉。GetParabolaPoints().ToArray();
elapsedTime=0;
持续时间=时间移动;
indexPosition=0;
路径位置=0;
右=0;
左=0;
while(右<点长度)
{
路径位置=延迟时间/持续时间;
indexPosition=路径位置*点。长度;
左=数学地板点(indexPosition);
右=数学中心点(indexPosition);
if(右<点长度)
{
t=未展开-左侧;
位置=矢量3.t(点[左]、点[右]、t);
projection.transform.position=位置;
}
其他的
{
projection.transform.position=points.Last();
}
elapsedTime+=Time.smoothDeltaTime;
收益返回空;
}
}
如果你从一个点移动到另一个点,你将根据你需要改变点集的次数得到一个滞后。试着把整个点集作为一条路径来考虑,并决定你在该路径上的位置(从[0,1]
)
如果在3秒内遍历整个路径,并且有1000个点,那么1.5秒是沿着我们的路径的0.5f,或者说500点
以下是单个运动帧的示例:
var points=newvector3[1000];
浮动持续时间=3f;
//Time.deltaTime是单个帧的持续时间,
//因此,这会将位置设置为“移动一帧后”
float pathPosition=Time.deltaTime/duration;//我们的[0,1]值
float indexPosition=pathPosition*points.Length;//在路径中的位置
int left=Mathf.FloorToInt(indexPosition);
int right=Mathf.ceiloint(indexPosition);
float t t=inexposition-left;//左右位置之间的百分比
向量3位置=向量3.Lerp(点[左]、点[右]、t);
如果您跟踪之前的路径位置或到目前为止看到的持续时间,则可以在每个帧上构建。不是朝着一个目标前进,而是找出你在整个穿越过程中的位置并直接到达那里。谢谢你回答@NSJacbo1,但我已经测试了你的方法,我一定是做错了什么,因为投射物闪烁但不移动,我已经附上了我在我的问题上如何使用你的代码,我做错了什么?这段代码并不打算按“原样”运行,而是显示我建议您实现的流程。希望这些注释能让想法的实现更清晰一些代码>到<代码>浮动路径位置=延迟时间/持续时间代码>。你也可以考虑在运动中使用一些平滑的方法,如果它仍然看起来很笨拙,并且在你的<代码>的时候把弹丸的位置设置到最后一点,而完成。Hi @ NSJACOB1令人敬畏的方法,多谢,但我仍然有麻烦。我已经用你的想法修改了代码,但是轨迹持续时间是2.4而不是3,8而不是10,分数越少,时间之间的差异越大,我做错了什么?我看不出任何明显的理由让你的代码比你预期的持续时间长得多,尽管
smoothDeltaTime
可能会引入一些延迟,这取决于帧的可变性。也许明天我会试着运行你为自己准备的,看看发生了什么。谢谢@NSJacob1,如果你想做和我一样的测试,使用这组分数,旅行持续时间是2秒而不是3:(0,0,0)(3.768777,2.606755,1.976568)(6.141703,3.53734,4.742089)(7.118778,2.791757,8.296565)(6.700002,0.3700044,12.64)
private IEnumerator MoveProjectileThroughTheParabola(float timeToMove)
{
Vector3[] points = parabolaDrawer.GetParabolaPoints().ToArray();
float elapsedTime = 0;
float duration = timeToMove;
while(elapsedTime < duration)
{
elapsedTime += Time.deltaTime;
float pathPosition = Time.deltaTime / duration;
float indexPosition = pathPosition * points.Length;
int left = Mathf.FloorToInt(indexPosition);
int right = Mathf.CeilToInt(indexPosition);
float t = indexPosition - left;
Vector3 position = Vector3.Lerp(points[left], points[right], t);
projectile.transform.position = position;
yield return new WaitForEndOfFrame();
}
}
private IEnumerator MoveProjectileThroughTheParabola(float timeToMove)
{
Vector3[] points = parabolaDrawer.GetParabolaPoints().ToArray();
elapsedTime = 0;
duration = timeToMove;
indexPosition = 0;
pathPosition = 0;
right = 0;
left = 0;
while (right < points.Length)
{
pathPosition = elapsedTime / duration;
indexPosition = pathPosition * points.Length;
left = Mathf.FloorToInt(indexPosition);
right = Mathf.CeilToInt(indexPosition);
if(right < points.Length)
{
t = indexPosition - left;
position = Vector3.LerpUnclamped(points[left], points[right], t);
projectile.transform.position = position;
}
else
{
projectile.transform.position = points.Last();
}
elapsedTime += Time.smoothDeltaTime;
yield return null;
}
}