Should Time.deltaTime produce the same results as if I used set intervals?

I’m trying to create a projectile that moves in an arc, along with an arcing line renderer to help aim it, they both use the same logic and the same values but their arcs aren’t the same.

For the line renderer, I calculate an array of vector3 positions at set intervals.

private Vector3[] CalculateArcArray()
    {
        for(int i = 0; i <= Resolution; i ++)
        {
            float t = 0.2f * i;
            ArcArray[i] = CalculateArcPoint(t);
        }
        LineStart = ArcArray[0];
        return ArcArray;
    }

    private Vector3 CalculateArcPoint(float t)
    {
        Vector3 FakeForward = transform.forward;
        FakeForward.y = 0f;
        FakeForward.Normalize();
        Vector3 HorizontalPosition = FakeForward * HorizontalSpeed * t;
        Vector3 VerticalPosition = Vector3.up * VerticalSpeed * t;
        VerticalSpeed -= Gravity * 0.2f;
        VerticalSpeed = Mathf.Clamp(VerticalSpeed, TerminalVelocity, InitialVerticalSpeed);
        Vector3 PlayerOffset = Player.transform.position + new Vector3(0, 1.5f, 0.1f);

        Vector3 ArcPoint = PlayerOffset + HorizontalPosition + VerticalPosition;
        return ArcPoint;
    }

For the projectile, I use the same calculations in CalculateArcPoint() but in the projectile’s update method with time.deltatime instead of t.

private void FixedUpdate()
    {
        Vector3 FakeForward = transform.forward;
        FakeForward.y = 0f;
        FakeForward.Normalize();
        Vector3 HorizontalPosition = FakeForward * HorizontalVelocity * Time.deltaTime;
        Vector3 VerticalPosition = Vector3.up * VerticalVelocity * Time.deltaTime;
        VerticalVelocity -= Gravity * Time.deltaTime;
        VerticalVelocity = Mathf.Clamp(VerticalVelocity, TerminalVelocity, InitialVerticalVelocity);

        transform.position += (HorizontalPosition + VerticalPosition);
    }

The arcs aren’t terribly different as they do start at the same trajectory but the projectile overshoots the line renderer once the latter reaches it’s peak, which suggests that gravity isn’t pulling it down as much as it should. They both have the same gravity value so I’m guessing the issue lies with the intervals/time.deltatime.

If I double the projectiles’ gravity, it works but this feels like a band aid to a problem I still don’t understand.

  1. What physics timestep are you using? In CalculateArcArray() it looks like you’re using timesteps of .2 seconds. That seems really large. Unity’s default physics timestep is .02 seconds. Different timesteps is going to change your trajectory, especially where constant acceleration like gravity is involved.

  2. Your calculations in each function are similar but I believe you will no matter what end up falling prey to slight differences due to floating point precision limits, since in CalculateArcPoint you’re using an absolute time for each position and in FixedUpdate you’re using incremental updates.

  3. Why not just calculate the trajectory once using CalculateArcArray(), and just lerp the projectile across that precalculated path in Update()?

  1. The line renderers’ script uses Update() but it calculates all the coordinates of the arc within one frame with 0.2 intervals in place of time. I used that value for the sake of the line renderer, which places a vertex between each vector, 0.2 gives me a smooth enough curve while displaying the full arc without adding too many vertices to the line. I’ve toyed around with the value but I haven’t noticed any significant changes to the curve beyond it’s smoothness.

  2. That makes sense, so would those slight differences add up until gravity is half as effective on the projectile?

  3. That method would work, infact I already have a boomerang type projectile that works that way. But I think it would be easier to expand on the projectiles movement (like adding a bounce or physics interactions) if I already had it’s velocity and Horizontal/vertical components.

If you need this, you could have your CalculateArcPoint function also store the instantaneous velocity at each point as well as its position. What I mean is this:

struct VelocityAndPosition {
  Vector3 position;
  Vector3 velocity;
}

private VelocityAndPosition[] CalculateArcArray()
{
    for(int i = 0; i <= Resolution; i ++)
    {
        float t = 0.2f * i;
        ArcArray[i] = CalculateArcPoint(t);
    }
    LineStart = ArcArray[0];
    return ArcArray;
}

private VelocityAndPosition CalculateArcPoint(float t)
{
    Vector3 FakeForward = transform.forward;
    FakeForward.y = 0f;
    FakeForward.Normalize();
    Vector3 HorizontalPosition = FakeForward * HorizontalSpeed * t;
    Vector3 VerticalPosition = Vector3.up * VerticalSpeed * t;
    VerticalSpeed -= Gravity * 0.2f;
    VerticalSpeed = Mathf.Clamp(VerticalSpeed, TerminalVelocity, InitialVerticalSpeed);
    Vector3 PlayerOffset = Player.transform.position + new Vector3(0, 1.5f, 0.1f);

    VelocityAndPosition toReturn;
    toReturn.position = PlayerOffset + HorizontalPosition + VerticalPosition;
    toReturn.velocity = new Vector3(HorizontalSpeed, VerticalSpeed, 0);
    return toReturn;
}

I think having different time steps is a lot more likely to cause this big discrepancy than floating point error but I’m not 100% sure what’s causing that.

1 Like