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