Rigidbody
Rigidbody hands a GameObject to the physics engine — gravity, forces, velocity, and collisions are computed by Unity Physics instead of your Update loop.
Imagine...
A Rigidbody is like an object's physics soul. Before it exists, a box is just a still image hanging in the air. After you add a Rigidbody, it becomes a body with real mass — pulled down by gravity, bouncing on impact, sliding under force. You push it with `AddForce()`, like a hand, instead of writing `transform.position` directly.
The concept in detail
A Rigidbody registers the GameObject with Unity Physics.
Main properties: mass (kg), drag (air resistance),
angularDrag (rotational resistance), useGravity,
isKinematic.
ForceMode: Force (continuous, uses mass),
Acceleration (continuous, ignores mass), Impulse (instant, uses mass —
typical for jump), VelocityChange (instant, ignores mass).
Kinematic Rigidbody:
isKinematic = true — still participates in collision detection but is not driven by
forces or gravity. Move it with MovePosition(). Use this for moving platforms and
animated objects.
Critical rule: never set
transform.position directly on a non-kinematic Rigidbody — that teleports the body
and breaks the simulation. Always use AddForce() or velocity.
Diagram: Forces & ForceMode
ForceMode Types
Force
Continuous, uses mass. Rockets, wind...
rb.AddForce(dir * 10f)Impulse
Instant, uses mass. Jumps, explosion knockback
rb.AddForce(Vector3.up * 5f, ForceMode.Impulse)VelocityChange
Instant, ignores mass. Sets velocity directly
rb.AddForce(dir, ForceMode.VelocityChange)Rigidbody Properties
Constraints (Freeze)
Hands-on steps
Add a Rigidbody component
Inspector → Add Component → Physics → Rigidbody. Also add a Collider if you want collisions.
Cache the Rigidbody in Awake
_rb = GetComponent<Rigidbody>() — then use it in FixedUpdate.
Move with forces in FixedUpdate
Do not write transform.position. Use AddForce() or set velocity.
Freeze Rotation for 2D top-down
Inspector → Constraints → Freeze Rotation X, Y, Z so the object does not tumble on impact.
Use isKinematic for moving platforms
A platform driven by animation → isKinematic = true + MovePosition().
Interactive simulator
Click the canvas to spawn objects. Tweak Gravity, Mass, and Drag, then press Force Up to apply an impulse.
Code example
BasicMove and jump with a Rigidbody.
using UnityEngine;
public class PhysicsPlayer : MonoBehaviour
{
[SerializeField] private float moveForce = 10f;
[SerializeField] private float jumpForce = 7f;
[SerializeField] private float maxSpeed = 8f;
private Rigidbody _rb;
private Vector3 _input;
private bool _grounded;
void Awake() => _rb = GetComponent<Rigidbody>();
void Update()
{
_input = new Vector3(Input.GetAxisRaw("Horizontal"), 0,
Input.GetAxisRaw("Vertical"));
if (Input.GetButtonDown("Jump") && _grounded)
_rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
void FixedUpdate()
{
// Cap speed on the horizontal plane
Vector3 flatVel = new Vector3(_rb.velocity.x, 0f, _rb.velocity.z);
if (flatVel.magnitude > maxSpeed)
_rb.velocity = flatVel.normalized * maxSpeed + Vector3.up * _rb.velocity.y;
_rb.AddForce(_input.normalized * moveForce, ForceMode.Force);
}
private void OnCollisionEnter(Collision col)
=> _grounded = col.gameObject.CompareTag("Ground");
private void OnCollisionExit(Collision col)
=> _grounded = false;
}Code example
AdvancedExplosion force with AddExplosionForce — fling bodies away from the blast center.
using UnityEngine;
public class Explosion : MonoBehaviour
{
[SerializeField] private float force = 500f;
[SerializeField] private float radius = 5f;
[SerializeField] private float upModifier = 0.5f;
public void Explode()
{
// Find every Collider inside the radius
Collider[] cols = Physics.OverlapSphere(transform.position, radius);
foreach (var col in cols)
{
var rb = col.GetComponent<Rigidbody>();
if (rb == null) continue;
// Unity scales the force by distance
rb.AddExplosionForce(force, transform.position, radius, upModifier);
}
// Visual effect + destroy
GetComponent<ParticleSystem>()?.Play();
Destroy(gameObject, 2f);
}
}📌 Quick recap
- ▸Forces → FixedUpdate; Input → Update
- ▸Jump:
AddForce(up, ForceMode.Impulse) - ▸Never set
transform.positionon a non-kinematic RB - ▸Moving platform → isKinematic + MovePosition
⚠️ Common mistakes
❌ Writing transform.position on a Rigidbody
Teleport — breaks physics, wall clipping, collision glitches
✅ rb.MovePosition() or velocity
❌ Physics code in Update instead of FixedUpdate
Out of sync with the physics timestep → jitter, tunneling
✅ Every AddForce/velocity call → FixedUpdate