Under Construction
Unity10 min110 views

Physics Tunneling

Minh Khoa

Minh Khoa

Author

1️⃣ What is the concept of tunneling?

Tunneling (object penetration) occurs when an object moves too fast between two frames (frame), causing the Physics system to not detect the collision in time.

Simply put: in frame 1, object A is in front of the wall,

in frame 2, A is already behind the wall → Unity never “sees” them collide.

🧩 Consequences:

  • OnCollisionEnter, OnTriggerEnter not called.

  • The object “passes through” another collider without any physical reaction.

  • Causes serious bugs in high-speed games (bullets, cars, slash attacks…)

    image.png

2️⃣ Technical causes

🔹 2.1. Unity Physics runs separately from Rendering

  • Each frame, Unity updates physics once per fixed timestep (Time.fixedDeltaTime – by default 0.02s = 50 FPS physics).
  • If an object moves quickly, between 2 physics updates, it has already jumped too far from the collider → the collision is not calculated.

🔹 2.2. The default Collision Detection mechanism is “Discrete”

  • Unity only checks the position at each physics step, without interpolating the path.
  • High speed = large jumps → the collider can be “missed”.

🔹 2.3. Timestep or Rigidbody inaccuracy

  • Fixed Timestep too large → the distance between physics frames is far apart.
  • Rigidbody interpolation is not enough → the displayed frame is “correct” but the physics “skips over” it.

3️⃣ Illustration of the “miss collision” mechanism

Frame 1:  O---|  (O trước tường)
Frame 2:        |---O  (O sau tường)
Kết quả: Không có frame nào thấy O chạm | → Không có collision!

If the speed is high enough, the object can “move past” the collider’s thickness in just 1 physics tick.


4️⃣ Fixes

✅ 4.1. Use Continuous Collision Detection

  • In RigidbodyCollision Detection:
    • Discrete: default (fast, cheap, easy to miss).
    • Continuous: calculates the movement path → detects collisions more accurately.
    • Continuous Dynamic: for fast-moving objects.
    • Continuous Speculative: newer Unity (: the strongest, but expensive CPU).

🧠 Recommendation:

  • Use Continuous Dynamic for fast objects with Rigidbody (bullets, projectiles, cars).
  • Set static colliders (walls, floors) to Continuous Static or leave it at default.

✅ 4.2. Reduce Fixed Timestep

  • In Edit → Project Settings → Time → Fixed Timestep.
  • Default 0.02s → can be reduced to 0.01 or 0.005.
  • Physics updates more often → fewer missed collisions.

⚠️ In return: CPU more expensive (because it increases the number of physics updates per frame).


✅ 4.3. Limit object speed

  • Set Rigidbody.maxLinearVelocity or clamp the speed yourself.
  • Do not allow “teleport” movement between frames.
  • For bullets → should raycast instead of using rigidbody velocity.

✅ 4.4. Use Raycast to check manually

  • Instead of relying entirely on the physics engine, you manually raycast in the movement direction.
Vector3 dir = rb.velocity.normalized;
float dist = rb.velocity.magnitude * Time.fixedDeltaTime;
if (Physics.Raycast(transform.position, dir, out RaycastHit hit, dist))
{
    // Xử lý va chạm thủ công
}
  • Especially useful for bullets or slash attacks – where you only need to know the instantaneous collision.

✅ 4.5. Use Rigidbody Interpolation

  • Helps display smoothly when FixedUpdate is lower than the framerate.
  • Does not directly solve tunneling, but improves display accuracy.

✅ 4.6. Thicker collider / Wider bounding box

  • If the collider is too thin (e.g. plane 0.001), collisions can easily be missed.
  • Thicker = larger check area → fewer misses.

✅ 4.7. Don’t mix Transform.Translate / MovePosition not standard

  • Don’t “teleport” an object with transform.position when it has a Rigidbody.
  • Use Rigidbody.MovePosition() or add force (AddForce, velocity)to let physics control the movement.