C# 如何在给定的时间内移动射弹穿过各个位置,而不考虑位置计数

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

我想在某个特定的时间内,通过一系列的位置来引导一个投射物

我的代码在位置计数不是很高时起作用,但是当列表包含1000个点时,,投射所花费的时间不一样,它明显增加

我移动射弹的代码如下:

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