Improvements to overshooting for slower computers

When I first saw the code for overshoot correction I wondered if it would work. Here’s the potential bug:

  • Imagine the projectile travels 100 units per frame.
  • In the current frame (at the start of Update()) it is at 51 units away.
  • Update() runs and puts you at 49 units away (but behind the unit)
  • The distance check fails because you were farther away before you began the update code so the update code has to run another frame before the projectile is farther away.

On slower PCs (like mine!) this bug triggers almost every time. Why? Because the projectile travels farther with each frame. On faster PCs the bullet would not travel as far each frame so you have finer degree of movement. When it overshoots on a faster PC, it will be by a negligible amount so you won’t notice.

So what to do?
Option 1: Increase moveSpeed to something like 1200 (instead of 200). This will almost certainly guarantee a significant overshoot, which will cause Hugo’s correction code to trigger sooner. Note this is still a bit of hack.
Option 2: Use dot products to detect a direction change. See below. A dot product will return 1 if the vectors are perfectly aligned, 0 if they are orthogonal, and -1 if they are aligned but in opposite directions and it will return all the numbers in between. So what this means is your dot product will be negative if the vectors are facing different directions. Thus if you calculate the move direction for the next frame within the current frame you can catch the overshoot with the current frame.

private void Update()
{
        Vector3 moveDir = (targetPosition - transform.position).normalized;

        float moveSpeed = 200f;
        transform.position += moveDir * moveSpeed * Time.deltaTime;

        Vector3 nextFrameMoveDir = (targetPosition - transform.position).normalized;
//for performance you don't need to normalize this second one I don't think.

        if (Vector3.Dot(moveDir, nextFrameMoveDir) <0)
        {
            transform.position = targetPosition;
            trailRenderer.transform.parent = null;
            Destroy(gameObject);
        }
}
3 Likes

I didn’t realize this had already been addressed in another thread on this topic. I saw it just now. Linking for completeness.

1 Like

For performance geeks, you can remove the second .normalize from my code. You’re only doing an expensive Distance, Normalize, Magnitude computation once in the whole loop now, which makes it more performant than the other proposals. Dot products are very cheap to compute.

As this thread was sparked by problems with slower computers, I felt it was important to try to make this code performant.

3 Likes

Privacy & Terms