Thursday, 18 June 2026

Unity Rigidbody Explained: A Complete Beginner's Guide

If you have already gone through our Character Controller guide, you learned how to move a player using controller.Move() — a system with no real physics behind it. Now we are switching to the opposite approach: letting Unity's physics engine do the moving for you.

That is exactly what a Rigidbody does. It is the component responsible for almost every physics-driven object in Unity — crates that tip over, ragdolls that collapse, vehicles that bounce on rough terrain, and balls that roll downhill. If it needs to react to gravity, forces, or collisions in a realistic way, a Rigidbody is almost always involved.

This guide starts from zero and builds up to a working pushable crate, a simple Rigidbody-based player, an explanation of how Rigidbody interacts with the Character Controller player from our earlier guide, and a full troubleshooting section for the errors every beginner runs into.


   

What Is a Rigidbody in Unity?

A Rigidbody is a Unity component that hands control of an object's movement over to Unity's physics engine. Once attached, the object will fall under gravity, respond to forces, bounce off collisions, and behave the way real objects behave — without you writing any movement code at all.

This is the opposite philosophy from the Character Controller. With Character Controller, you write every line of movement logic yourself and the component just stops you from passing through walls. With Rigidbody, you mostly describe forces and let Unity's physics simulation calculate position, rotation, and collision response on its own.

Under the hood, a Rigidbody works together with a Collider component (Box Collider, Sphere Collider, Capsule Collider, or Mesh Collider). The Rigidbody provides the physics behavior — mass, drag, gravity — while the Collider defines the actual shape used for detecting collisions. You almost always need both on the same object for physics to work correctly.

Why Rigidbody Matters

Once you start building a real game, you will run into situations the Character Controller simply cannot handle on its own: an explosion that should send debris flying, a crate the player can push, a vehicle that should respond to bumps in the road, or a ragdoll that collapses realistically when an enemy dies.

A common mistake beginners make is trying to force the Character Controller to do all of this through more and more custom script logic. When I first learned this concept, I tried writing my own "push" system for crates using nothing but Character Controller collision events, and it was far more code, far less reliable, and far less satisfying than just adding a Rigidbody to the crate and letting physics handle it.

Rigidbody exists precisely because rebuilding physics by hand is slow and error-prone. Learning when to reach for it instead of writing custom movement code will save you a significant amount of time.



When To Use a Rigidbody

  • You need objects that fall, roll, tip over, or bounce realistically — crates, barrels, balls, and debris.
  • You are building vehicles that should respond to bumps, jumps, and slopes using physics rather than scripted movement.
  • You want characters that can be pushed by explosions, wind, or other physics forces.
  • You are building a ragdoll system, where each body part needs its own Rigidbody connected by joints.
  • You want objects that can collide with and push each other realistically, like a pile of boxes.

When Not To Use a Rigidbody

  • You need precise, predictable player movement with no unwanted sliding or momentum — that is what Character Controller is for.
  • You are building simple UI-driven movement, like a 2D platformer character that needs exact, frame-perfect jump arcs (some 2D games do use Rigidbody2D for this, but it requires very careful tuning).
  • You want an object that never moves and exists only to block other physics objects — in that case, use a Collider with no Rigidbody at all, often called a "static collider."
  • You need an object to follow an exact scripted path regardless of what it collides with, such as a moving platform on a fixed track — this calls for a Kinematic Rigidbody, which we will cover shortly.

This part usually confuses new users: it is entirely normal, and in fact common, to use both Character Controller and Rigidbody in the same scene for different objects. Your player can use Character Controller while every crate, ragdoll, and vehicle in the same level uses Rigidbody.

Advantages of Rigidbody

Advantage Why It Helps
Realistic physics for free Gravity, momentum, and collision response are handled automatically by Unity's physics engine.
Objects interact with each other Two Rigidbody objects that collide will push, bounce, or stack realistically without extra code.
Forces feel natural AddForce(), explosions, and wind zones all "just work" once a Rigidbody is present.
Great for environmental objects Crates, debris, ragdolls, and vehicles are all easiest to build using Rigidbody.
Built-in collision events OnCollisionEnter and OnTriggerEnter give you easy hooks for sound effects, damage, or scoring.

Disadvantages of Rigidbody

Disadvantage Why It Matters
Less predictable movement Momentum and friction can cause sliding or bouncing that is hard to control precisely for player characters.
Requires tuning Mass, drag, angular drag, and physics materials all need adjustment to feel right, unlike Character Controller's simpler setup.
Can tunnel through thin colliders at high speed Fast-moving Rigidbody objects can pass through thin walls unless Collision Detection mode is adjusted.
Physics runs in FixedUpdate, not Update Beginners often write physics code in Update() and get inconsistent or frame-rate-dependent results.
Harder to get exact, repeatable movement Two physics-based jumps can land in very slightly different spots due to floating point and collision timing differences.



Project Setup

Unity Version

This guide works in Unity 2021 LTS, Unity 2022 LTS, and Unity 6. The Rigidbody component's core fields have stayed consistent across these versions.

Recommended Folder Structure

If you are continuing in the same project as the Character Controller and Input System guides, add these folders if you have not already:

  • Assets/Scripts — your C# scripts, including the ones from this guide.
  • Assets/Prefabs — save your crate and Rigidbody player here once working.
  • Assets/Physics Materials — store any custom Physics Material assets here.

Building the Test Scene

  1. Right-click in the Hierarchy and choose 3D Object > Plane for the floor, if you do not already have one.
  2. Right-click again and choose 3D Object > Cube. Rename it Crate.
  3. Position the Crate slightly above the floor, for example at (0, 1, 0), so it visibly falls when you press Play.

Adding the Rigidbody Component

  1. Select the Crate object.
  2. Click Add Component and search for Rigidbody.
  3. Press Play.

Your crate will immediately fall and land on the floor. That is the entire setup required for basic gravity-driven physics — no script needed. This is the simplest possible demonstration of what makes Rigidbody powerful: gravity, falling, and landing all happened automatically.

Understanding Each Property

Property What It Does Typical Beginner Setting
Mass How heavy the object is. Heavier objects need more force to move and push lighter objects more easily. 1 (default, fine for most small objects)
Drag Air resistance that slows down movement over time. Higher drag makes the object stop faster. 0 - 1 for most objects
Angular Drag Same idea as Drag, but for rotation instead of movement. 0.05 (default)
Use Gravity Whether the object falls due to gravity. Turn off for floating objects. Checked (on) for most objects
Is Kinematic When checked, physics forces and gravity are ignored, but the object can still be moved by script and will still register collisions. Unchecked, unless building a scripted moving platform
Collision Detection Controls how carefully Unity checks for collisions. "Continuous" prevents fast objects from passing through thin colliders. Discrete for slow objects, Continuous for fast/small objects
Interpolate Smooths visual movement between physics steps, reducing visible jitter on moving Rigidbody objects. Interpolate, for camera-followed objects

A quick rule of thumb: if an object moves fast and is small (like a thrown ball or a bullet), set Collision Detection to Continuous or Continuous Dynamic. The default Discrete mode checks for collisions only at fixed points in time, which can let fast, thin objects "tunnel" straight through walls without ever registering a hit.



Writing Your First Physics Script: Pushing the Crate

Gravity alone is not very interesting. Let's add a script that lets the player push the crate using forces — the core idea behind almost every physics-driven interaction in Unity.

Create a new script named PushableCrate and attach it to your Crate object alongside the Rigidbody.

using UnityEngine;

public class PushableCrate : MonoBehaviour
{
    public float pushForce = 5f;

    private Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Player"))
        {
            Vector3 pushDirection = collision.transform.forward;
            rb.AddForce(pushDirection * pushForce, ForceMode.Impulse);
        }
    }
}

For this to work, tag your Player object as "Player" (select it, use the Tag dropdown at the top of the Inspector, and choose or create "Player"). Now when your Character Controller player from the earlier guide walks into the crate, it will be shoved forward.

Line By Line Explanation

pushForce is a public variable controlling how hard the crate gets shoved. Making it public lets you tune the feel directly in the Inspector without touching code.

rb = GetComponent<Rigidbody>(); runs once in Start() and stores a reference to this object's own Rigidbody, so we can call physics functions on it later without looking it up again every frame.

OnCollisionEnter(Collision collision) is a built-in Unity function that runs automatically the moment this object's collider touches another non-trigger collider. The Collision parameter contains useful information about what was hit and how.

collision.gameObject.CompareTag("Player") checks whether the object that collided with the crate is tagged "Player". This prevents every random object in the scene from pushing the crate — only the player can.

collision.transform.forward gets the direction the colliding object (the player) is facing, so the crate gets pushed away from the player rather than in some fixed direction.

rb.AddForce(pushDirection * pushForce, ForceMode.Impulse); is the actual physics push. AddForce() applies a force to the Rigidbody, and Unity's physics engine handles everything from there — acceleration, friction with the floor, and eventually slowing to a stop.

Understanding ForceMode

The second argument to AddForce() matters more than beginners expect.

ForceMode Best For
Force Continuous push applied every frame, like wind or a rocket engine. Affected by mass.
Impulse An instant, one-time push, like a punch, an explosion, or a single shove. Affected by mass.
VelocityChange An instant push that ignores mass entirely — useful when you want the same exact speed change regardless of how heavy the object is.
Acceleration A continuous push that ignores mass, similar to how gravity affects all objects equally regardless of weight.

Using Force when you meant Impulse (or vice versa) is one of the most common reasons a "push" feels far too weak or far too strong. Force needs to be applied every frame in FixedUpdate() to feel like a steady push; Impulse is meant to be called once.



A Real Example: Building a Simple Rigidbody Player

Let's look at a simple example of moving a character using Rigidbody instead of Character Controller, so you can feel the practical difference.

using UnityEngine;

public class RigidbodyPlayerMovement : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float jumpForce = 7f;

    private Rigidbody rb;
    private bool isGrounded;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        float moveX = Input.GetAxis("Horizontal");
        float moveZ = Input.GetAxis("Vertical");

        Vector3 move = new Vector3(moveX, 0f, moveZ) * moveSpeed;
        rb.MovePosition(rb.position + move * Time.fixedDeltaTime);
    }

    void Update()
    {
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
        }
    }

    void OnCollisionStay(Collision collision)
    {
        isGrounded = true;
    }

    void OnCollisionExit(Collision collision)
    {
        isGrounded = false;
    }
}

Notice the structural difference from the Character Controller script in our earlier guide: movement logic lives in FixedUpdate() instead of Update(), and we use rb.MovePosition() instead of controller.Move(). Jump input detection still happens in Update() since input should always be checked every rendered frame, not every physics step.

Why FixedUpdate()? Unity's physics engine runs on its own fixed time step, separate from your rendering frame rate. Reading or writing Rigidbody data inside Update() can cause stuttering or inconsistent behavior, because Update() runs at a variable rate while physics runs at a fixed rate. FixedUpdate() runs in sync with the physics engine, which is why movement code involving a Rigidbody belongs there.

rb.MovePosition() moves the Rigidbody while still respecting collisions, which is generally smoother and more predictable than directly setting rb.velocity for character-style movement.

This is a good moment for an honest comparison: this Rigidbody player will feel different from the Character Controller version — slightly more "slidey," with momentum that needs tuning through Drag. That difference is not a bug. It is the fundamental trade-off between the two systems.

Beginner Mistakes

  • Writing movement code in Update() instead of FixedUpdate(). This causes stuttery, frame-rate-dependent movement for Rigidbody objects.
  • Setting transform.position directly on a non-kinematic Rigidbody. This bypasses physics entirely and can cause the object to get stuck in walls or behave unpredictably on the next physics step. Use MovePosition() or AddForce() instead.
  • Forgetting a Collider. A Rigidbody with no Collider will fall forever and never register any collisions — physics needs both components together.
  • Using ForceMode.Force for a one-time push. Force is meant to be applied repeatedly across multiple frames; using it once produces a barely noticeable nudge. Use Impulse for single pushes.
  • Not adjusting Drag, leading to objects that slide forever. Default Drag of 0 means no air resistance at all — objects will keep moving until something stops them.
  • Adding a Rigidbody to the same object as a Character Controller. The two systems conflict; Character Controller already handles its own movement and does not need a Rigidbody alongside it.
  • Forgetting to tag objects correctly for collision checks. Scripts checking CompareTag("Player") will silently fail to trigger if the tag was never actually assigned in the Inspector.

Troubleshooting Guide

Problem: My Rigidbody object falls through the floor.

Likely cause: The floor has no Collider, or the object is moving fast enough to tunnel through a thin Collider in a single physics step.

Fix: Confirm the floor has a Collider component (a default Plane includes one). For fast objects, set Collision Detection to Continuous or Continuous Dynamic.

Problem: My object will not move at all when I call AddForce().

Likely cause: Is Kinematic is checked, which disables all physics forces, or the script is calling AddForce() on the wrong Rigidbody reference.

Fix: Uncheck Is Kinematic in the Inspector if you want forces to apply. Confirm GetComponent<Rigidbody>() is finding the correct object.

Problem: My object slides forever and never stops.

Likely cause: Drag is set to 0, and there is no friction-providing Physics Material on the colliders involved.

Fix: Increase Drag on the Rigidbody, or create a Physics Material with higher friction and assign it to the relevant Colliders.

Problem: My object jitters or vibrates while resting on the ground.

Likely cause: Conflicting collision response, often caused by overlapping colliders at spawn or extremely low Mass values causing unstable physics calculations.

Fix: Make sure objects do not spawn overlapping each other. Increase Mass slightly if it is set unusually low (below 0.1).

Problem: Two Rigidbody objects pass through each other instead of colliding.

Likely cause: One or both Colliders are set to "Is Trigger", which disables physical collision response entirely and only fires trigger events instead.

Fix: Uncheck "Is Trigger" on the Collider if you want physical collision response rather than just an OnTriggerEnter event.

Problem: My Rigidbody player movement feels stuttery.

Likely cause: Movement code is running in Update() instead of FixedUpdate(), or the Rigidbody's Interpolate setting is off, causing visible jitter between physics steps when the camera follows the object.

Fix: Move physics-related movement code into FixedUpdate(). Set Interpolate to "Interpolate" on the Rigidbody for smoother visuals.



Rigidbody and Character Controller Together

Since you already built a Character Controller player in our earlier guide, here is exactly how the two systems interact in the same scene.

Character Controller Pushing a Rigidbody Crate

This is exactly the PushableCrate script from earlier in this guide. Character Controller does not apply physics forces automatically when it touches a Rigidbody — that is why the script explicitly calls AddForce() inside OnCollisionEnter(). Without that script, your Character Controller player would simply stop against the crate as if it were a wall, since Character Controller treats every collider as solid geometry unless told otherwise.

A More Advanced Push Method: OnControllerColliderHit

For more natural, continuous pushing (rather than a single impulse on first contact), Character Controller offers a dedicated callback function specifically for this purpose.

using UnityEngine;

public class CharacterPushesRigidbody : MonoBehaviour
{
    public float pushPower = 2f;

    void OnControllerColliderHit(ControllerColliderHit hit)
    {
        Rigidbody body = hit.collider.attachedRigidbody;

        if (body == null || body.isKinematic)
        {
            return;
        }

        Vector3 pushDir = new Vector3(hit.moveDirection.x, 0f, hit.moveDirection.z);
        body.AddForce(pushDir * pushPower, ForceMode.Impulse);
    }
}

Attach this script to your Character Controller player (not the crate). OnControllerColliderHit() fires continuously while the Character Controller is touching another collider, giving a smoother, ongoing push rather than the one-time impulse from the crate-side script. hit.collider.attachedRigidbody finds the Rigidbody on whatever was hit, and the null/isKinematic check prevents errors when the player walks into static scenery that has no Rigidbody at all.

Ragdolls: Where Pure Rigidbody Takes Over

A full ragdoll system replaces your Character Controller character's animated skeleton with individual Rigidbody components on each limb, connected together using Joint components (commonly Configurable Joints). When a ragdoll activates — usually when a character dies — your Character Controller and its movement script get disabled, and physics takes over completely, letting the body fall and tumble realistically.

Building a full ragdoll rig is a deep topic on its own, but the key beginner takeaway is this: Character Controller and Rigidbody are not just compatible, they are commonly designed to hand off control to each other depending on the situation — walking and running use Character Controller, while death, explosions, and impacts use Rigidbody.



Best Practices

  • Always pair a Rigidbody with a Collider — neither one is very useful alone.
  • Write all Rigidbody movement and force code inside FixedUpdate(), and keep input reading in Update().
  • Use MovePosition() instead of directly setting transform.position when moving a non-kinematic Rigidbody.
  • Choose the correct ForceMode for the situation: Impulse for one-time pushes, Force for continuous pushes applied every FixedUpdate().
  • Set Collision Detection to Continuous for small, fast-moving objects to avoid tunneling through thin colliders.
  • Never attach a Rigidbody to the same object as a Character Controller — choose one movement system per object.
  • Use Is Kinematic for objects that need to move along a fixed script-controlled path (like elevators or moving platforms) while still registering collisions.

Action Steps

  1. Add a Rigidbody to a simple cube and press Play to see gravity working with zero code.
  2. Build the PushableCrate script and tag your player as "Player" to test pushing.
  3. Build the RigidbodyPlayerMovement script on a separate test object to feel the difference from Character Controller movement.
  4. Add the CharacterPushesRigidbody script to your existing Character Controller player from the earlier guide and test pushing a crate naturally while walking.
  5. Experiment with Drag and Mass values until pushing feels right for your game.

Learning Roadmap

  1. Get comfortable with basic Rigidbody gravity and AddForce() as shown in this guide.
  2. Practice the different ForceMode options until the difference between Impulse and Force is intuitive.
  3. Combine a Character Controller player with Rigidbody props in the same scene using OnControllerColliderHit().
  4. Explore Joint components (Configurable Joint, Hinge Joint) for doors, ragdolls, and swinging objects.
  5. Move on to Unity Mobile Optimization to make sure your physics objects perform well on lower-powered devices.

Next Topics To Learn

No comments:

Post a Comment

How to Use ElevenLabs for Game Development: AI Voice Acting, NPC Dialogue, and Sound Design

Most indie games ship without voice acting. Not because developers do not want it, but because hiring voice actors is expensive, scheduling ...