Bullet/Projectile Collision Question

In the image above, I’ve illustrated (very crudely in Paint) a problem I anticipate within Unity3D (or any game engine to be honest), regarding projectile/bullet collision.

If I have a bullet prefab game object instantiated at the tip of a gun, and it travels at 2 metres per second, and an enemy is standing 3 metres away, what would happen if my framespersecond was at 1fps?

If my game was running so slowly, would that collision happen?
In my mind, the game is running at 1 frame per second. So in Frame 1 the bullet is just in front of the gun. Frame 2 the bullet is at 2metres, at frame 3 the bullet is at 4 metres, etc.
So if the game was running at 1fps, and the bullet moving at 2 metres per second, then any enemies standing in odd numbered distance intervals (3,5,7,9 etc) would not trigger a collision?

Or does Unity’s FixedUpdate method deal with physics in such a way, that it detects the collision, regardless of how many visual frames it renders per second? I think I remember reading somewhere, the fixedupdate happens regardless of your FPS, it occurs at fixed intervals in the game and is not affected by your FPS output?

I’m trying to understand how Unity deals with collisions, and how accurate/reliable this is for someone on a PC with low FPS. I’m sure no one would even play a game at 1fps, but I’m wondering what would happen if maybe they had an FPS spike too low for a brief moment, would they be cheated/robbed of a potential kill because of this ‘bug’ in my game?

If my game was running so slowly, would that collision happen?

Nope! Not by default, anyway.

You’ve discovered the difference between discrete and continuous collision.

In discrete collision, the position of each object is checked once per frame, and it’s entirely possible for fast-moving objects to go completely through colliders without ever “touching” them. This is the default behavior for most colliders in most engines, because it’s very performant.

Continuous collision is good and bad. It’s good because it’s more accurate and will catch things like a fast-moving bullet that hits a wall. It’s bad because it’s more work for the computer, and that can bog down performance if you’re not careful.

From the Unity manual, you can apply several collision detection models to a rigidbody:

  • Discrete: Use Discreet collision detection against all other colliders in the scene. Other colliders will use Discreet collision detection when testing for collision against it. Used for normal collisions (This is the default value).
  • Continuous: Use Discrete collision detection against dynamic colliders (with a rigidbody) and continuous collision detection against static MeshColliders (without a rigidbody). Rigidbodies set to Continuous Dynamic will use continuous collision detection when testing for collision against this rigidbody. Other rigidbodies will use Discreet Collision detection. Used for objects which the Continuous Dynamic detection needs to collide with. (This has a big impact on physics performance, leave it set to Discrete, if you don’t have issues with collisions of fast objects)
  • Continuous Dynamic: Use continuous collision detection against objects set to Continuous and Continuous Dynamic Collision. It will also use continuous collision detection against static MeshColliders (without a rigidbody). For all other colliders it uses discreet collision detection. Used for fast moving objects.

So, for example, you might set bullets to continuous dynamic and walls to continuous.

Side note: when it comes to bullets, lasers, and similarly instantaneous movement, it is sometimes simpler to simulate all of this behavior by raycasting.

Hello.
I find so far this is bit more accurate than colliders for me atm. its bit late but it might help other ppl like me.

private RaycastHit myHit;
private Vector3[] oldFramesVector = new Vector3[5];
float testVelocity = 45f;

void Update() {
    // simple motor
    transform.Translate(Vector3.forward * testVelocity * Time.deltaTime);
    //hit detection for fast moving objects
    if (oldFramesVector[4] != Vector3.zero) {
        for (int i = 0; i < oldFramesVector.Length; i++) {
            if (Physics.Linecast(transform.position,
                oldFramesVector*, out myHit)) {*

if (myHit.transform.gameObject.name !=
“object who created this one”) {
print("did hit " + myHit.transform.name +
" coll check succed on : " + i + " frame ");
break;
}
}
}
}
if (oldFramesVector[0] != transform.position) {
for (int i = oldFramesVector.Length; i > 0 - 1; i–) {
if (i + 1 < oldFramesVector.Length) {
oldFramesVector[i + 1] = oldFramesVector*;*
}
if (i == 0) {
oldFramesVector = transform.position;
}
}
}
}