Summary

Rigidbody2D is the Unity component that makes a 2D GameObject participate in the physics simulation. It enables realistic movement driven by forces and velocities, and is required for OnCollisionEnter2D and OnTriggerEnter2D callbacks to fire on a moving object. There are three body types, each suited to a different role. Physics-related code belongs in FixedUpdate, which runs on a fixed timestep independent of frame rate.


Key ideas

Body types:

Body typeBehaviourTypical use
DynamicFully simulated — responds to forces, gravity, and collisionsMoving enemies, projectiles, falling objects
KinematicMoves via script only — not affected by forces or gravity; still detects collisionsPlayer characters, moving platforms
StaticDoes not moveWalls, floors, static hazards

Gravity Scale: How strongly gravity pulls the object. Set to 0 for top-down 2D games or for kinematic players that manage their own movement.

Freeze Rotation Z: Prevents the physics engine from rotating the object when it collides. Almost always enabled on player characters — a player that tips over when touching a wall is rarely intentional.

FixedUpdate(): The correct place for all physics and Rigidbody2D calls. It runs on Unity’s fixed timestep (default 50 times per second), independent of frame rate. Calling physics in Update causes frame-rate-dependent behaviour — the physics will feel different on machines with different performance.

rb.linearVelocity (Unity 6) / rb.velocity (older Unity): Direct velocity assignment gives crisp, predictable movement. Setting velocity directly is preferred for character movement over AddForce, which introduces acceleration drift.

AddForce(direction * magnitude, ForceMode2D.Impulse): Applies the entire force in a single physics step. Use for one-shot impulses: knockback, jump, explosion.

Vector2.normalized: Returns a direction vector with a magnitude of exactly 1. Normalising before multiplying by speed prevents diagonal movement from being faster than horizontal or vertical movement (diagonal magnitude is √2 ≈ 1.41 without normalisation).

Vector2.ClampMagnitude(velocity, maxSpeed): Limits the magnitude of a vector without changing its direction. Use as a speed cap to prevent velocity accumulating beyond a safe maximum.


In practice

Caching Rigidbody2D in Start:

private Rigidbody2D rb;
 
private void Awake()
{
    rb = GetComponent<Rigidbody2D>();
    if (rb == null) Debug.LogError("[PlayerPhysics] No Rigidbody2D found!");
}

Physics movement in FixedUpdate:

private void FixedUpdate()
{
    HandleMovement();
    EnforceSpeedCap();
}
 
private void HandleMovement()
{
    float h = Input.GetAxisRaw("Horizontal");
    float v = Input.GetAxisRaw("Vertical");
 
    // Normalise: prevents diagonal speed boost
    Vector2 moveDir = new Vector2(h, v).normalized;
 
    // Direct velocity assignment — crisp, predictable
    rb.linearVelocity = moveDir * moveSpeed;
}
 
private void EnforceSpeedCap()
{
    // Preserves direction while clamping magnitude
    rb.linearVelocity = Vector2.ClampMagnitude(rb.linearVelocity, maxSpeed);
}

Knockback impulse:

public void ApplyKnockback(Vector2 sourcePosition)
{
    // Direction: away from the damage source
    Vector2 direction = ((Vector2)transform.position - sourcePosition).normalized;
 
    rb.linearVelocity = Vector2.zero;  // clear existing velocity for clean impulse
    rb.AddForce(direction * knockbackForce, ForceMode2D.Impulse);
}

Invoke for timed callbacks (e.g. ending a knockback window):

isKnockedBack = true;
Invoke("EndKnockback", knockbackDuration);  // calls EndKnockback() after N seconds
 
private void EndKnockback()
{
    isKnockedBack = false;
}

Inspector setup checklist

For a typical 2D player character:

  • Body Type: Kinematic (if script-driven) or Dynamic (if physics-driven)
  • Gravity Scale: 0 for top-down; keep default for platformer
  • Freeze Rotation → Z: enabled (prevents tipping on collision)
  • Attach the Rigidbody2D to the same GameObject as the movement script

Gotchas

  • Never use transform.Translate or set transform.position directly on a Dynamic Rigidbody2D — this bypasses the physics engine and causes jitter, missed collisions, and tunnelling. Use rb.linearVelocity, AddForce, or (for Kinematic) rb.MovePosition.
  • Read Input in Update; apply it in FixedUpdate. Calling Input.GetAxisRaw in FixedUpdate can miss input events that occurred between physics steps.
  • rb.linearVelocity is the Unity 6 API name. In older Unity versions (pre-6), the property is rb.velocity. Both refer to the same thing.