UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
UNITY PHYSICS SYSTEMS
A Complete Developer's Handbook
From Newton's Laws to Arcade Helicopters, Bikes & Ragdolls
Chapters Covered
1 — Real Physics Founda�ons (Forces, Torque, Vectors)
2 — Unity's Physics Engine (Rigidbody, Colliders, Layers)
3 — Raycasts & Spa�al Queries
4 — Spring & Suspension Systems
5 — Vehicle Physics (Cars, Bikes, Hovercra�s)
6 — Helicopter Physics
7 — Ragdoll & Joint Systems
8 — Physics Simula�ons (Cloth, Fluid, Projec�les)
9 — Modular Architecture for Physics Systems
10 — Debugging, Tuning & Performance
Page 1
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
CH
Real Physics Founda�ons
1 Newton's Laws · Forces · Vectors · Torque · Energy
Before wri�ng a single line of Unity code, you need to understand the physics that code is simula�ng. This
chapter covers the real-world physics principles that everything in this book is built on. You will see these
concepts directly map to Unity API calls.
1.1 Newton's Three Laws — The Founda�on of Everything
Every physics system you'll ever build is an applica�on of these three laws.
Law 1: Iner�a
An object at rest stays at rest. An object in mo�on stays in mo�on at the same velocity — unless acted on by a
net external force.
Net Force = 0 → Constant Velocity (including zero velocity)
In Unity: your Rigidbody keeps moving forever unless drag or a counter-force stops it. This is why se�ng [Link]
to 0 makes objects slide indefinitely on ice.
UNITY LINK: [Link] persists between frames. You don't need to re-apply a velocity
KEY
every frame — only apply forces to change it.
Law 2: F = ma (Force = Mass × Accelera�on)
The net force on an object equals its mass �mes its accelera�on. This is the most important equa�on in game
physics.
F = m × a → a = F / m
In Unity: [Link](force) adds to net force. The Rigidbody's mass then determines how much that force
accelerates the object. A force of 1000N on a 1kg object accelerates it at 1000 m/s². On a 100kg object, the same
force only gives 10 m/s².
// F = ma in Unity:
float desiredAcceleration = 15f; // m/s²
float force = [Link] * desiredAcceleration;
Page 2
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
[Link]([Link] * force, [Link]);
// This gives the SAME acceleration regardless of mass.
// Always scale forces by mass if you want consistent feel.
Law 3: Equal and Opposite Reac�on
For every force, there is an equal and opposite force. Your engine pushing the car forward pushes the ground
backward. The ground pushes the car forward equally. In Unity this is handled automa�cally by the physics
engine through collision contacts.
1.2 Vectors — Direc�on + Magnitude
Physics is inseparable from vectors. A vector has both direc�on and magnitude (length).
Opera�on Physics Use
[Link] The length (speed if velocity, force if force vector)
[Link] Same direc�on, length exactly 1. Use for direc�on only.
[Link](a, b) How much two vectors point the same way. Returns -1 to 1.
[Link](a, b) A vector perpendicular to both. Used for torque axes.
[Link](a, b, t) Smoothly blend between two posi�ons or direc�ons.
[Link](a, b, t) Spherically interpolate — be�er for direc�ons/rota�ons.
// DOT PRODUCT: Is the car moving forward or backward?
float forwardSpeed = [Link]([Link], [Link]);
// forwardSpeed > 0 = moving forward
// forwardSpeed < 0 = moving backward
// forwardSpeed = 0 = moving perfectly sideways
// CROSS PRODUCT: Tilt correction axis
// Find the rotation axis needed to go from [Link] to [Link]
Vector3 correctionAxis = [Link]([Link], [Link]);
// Apply torque along that axis to self-right the vehicle
[Link](correctionAxis * strength, [Link]);
// MAGNITUDE vs SQRMAGNITUDE:
// SqrMagnitude is cheaper (no square root) — use for comparisons
if ([Link] > maxSpeed * maxSpeed) { /* clamp */ }
Page 3
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
1.3 Torque — Rota�onal Force
Torque is the rota�onal equivalent of force. It causes angular accelera�on — spinning, �l�ng, yawing.
Torque = Force × Lever Arm Distance
Torque has both magnitude (how strong) and axis (which direc�on to spin). The axis is a Vector3 poin�ng in the
direc�on you'd push a right-hand-rule screw — fingers curl in the rota�on direc�on, thumb points along the axis.
// Torque examples:
// Yaw (rotate left/right): axis = world up
[Link]([Link] * torqueAmount, [Link]);
// Pitch (nose up/down): axis = car's right
[Link]([Link] * pitchAmount, [Link]);
// Roll (tilt sideways): axis = car's forward
[Link]([Link] * rollAmount, [Link]);
// Self-righting: push towards world up
Vector3 tiltError = [Link]([Link], [Link]);
[Link](tiltError * antiRollStrength, [Link]);
1.4 Energy, Drag, and Damping
Drag is the force opposing mo�on. In air and water, drag scales with velocity squared. In Unity's Rigidbody, drag is
simplified to linear drag (force propor�onal to velocity). You can switch between modes manually.
Drag Force = -drag_coefficient × velocity
// Linear drag (built-in): scales linearly with speed
[Link] = 2f; // Unity applies -2 * velocity each frame
// Manual quadratic drag (more realistic at high speed):
float speed = [Link];
Vector3 dragForce = -[Link] * (dragCoeff * speed * speed);
[Link](dragForce, [Link]);
// Angular drag: kills rotational spin
[Link] = 5f;
Quadra�c drag ma�ers for helicopter rotors, bullets, and any high-speed simula�on. Linear
TIP
drag is fine for cars and simple vehicles.
Page 4
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
1.5 The Physics Update Loop
Unity runs physics on a fixed �mestep (default 0.02s = 50Hz). This is separate from the render frame rate. You
MUST understand this split.
Method When to Use It
Update() Runs every render frame. Variable delta �me. Use for input polling, visual
updates, UI.
FixedUpdate() Runs at fixed physics �mestep (Time.fixedDeltaTime). Use for ALL
AddForce, velocity reads, physics queries.
LateUpdate() Runs a�er all Updates. Use for camera follow, visual mesh adjustments
a�er physics se�le.
// CORRECT pattern:
private float throttleInput;
void Update() // variable framerate
{
throttleInput = [Link]("Vertical"); // read input here
}
void FixedUpdate() // fixed physics rate
{
// Apply physics here using cached input
[Link]([Link] * throttleInput * force, [Link]);
}
// WRONG: reading input in FixedUpdate can miss frames!
// WRONG: calling [Link] in Update gives inconsistent results!
Page 5
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
CH
Unity's Physics Engine
2 Rigidbody · Colliders · Materials · Layers · ForceModes
Unity uses NVIDIA PhysX under the hood. Understanding what PhysX does automa�cally versus what you control
manually is cri�cal for building reliable physics systems.
2.1 The Rigidbody Component
Rigidbody is the component that makes an object par�cipate in physics simula�on. Without it, an object is just a
sta�c transform — it does not move or react to forces.
Property Purpose
mass Resistance to linear accelera�on. Scale forces by mass for consistent feel.
linearDamping Linear drag. Simulates air resistance on movement.
angularDamping Rota�onal drag. Kills spin. Set high (8-15) for vehicles to prevent tumbling.
useGravity Toggle gravity. Disable for hovercra�s, helicopters, space ships.
isKinema�c Physics won't simulate this body, but it can s�ll affect others. Use for
animated pla�orms.
interpola�on Smooths Rigidbody posi�on between fixed �mesteps. Always set
Interpolate for player vehicles.
constraints Freeze posi�on or rota�on on specific axes. Useful for 2.5D games.
centerOfMass Override the calculated center of mass. Lower = more stable. Very
important for cars.
solverItera�ons How many �mes PhysX resolves constraints. Raise to 12+ to reduce ji�er.
2.2 ForceMode — The Most Important Enum You'll Use
Page 6
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
Every AddForce call takes a ForceMode. Ge�ng this wrong is the #1 cause of physics feeling wrong.
ForceMode Behavior
[Link] Con�nuous force (Newtons). Applied over �me. F = mass × accelera�on.
USE THIS for engines, thrust, wind.
[Link]�on Con�nuous accelera�on (m/s²). Ignores mass. Good for gravity-like forces
where all objects should respond equally.
[Link] Instant velocity change scaled by mass (kg·m/s). USE THIS for jumps,
explosions, ramp launches.
[Link] Instant velocity change, ignores mass. Good for teleport-style movement.
// [Link] — continuous engine thrust
// Applied every FixedUpdate. Scales correctly with mass.
[Link]([Link] * engineNewtons, [Link]);
// [Link] — ramp launch, jump, explosion
// Applied once. To get consistent height regardless of mass:
float jumpHeight = 5f;
float jumpImpulse = [Link] * [Link](2f * [Link] * jumpHeight);
[Link]([Link] * jumpImpulse, [Link]);
// [Link] — same-gravity for all objects
// Like adding gravity on a specific axis regardless of mass
[Link]([Link] * 9.81f, [Link]);
WARNIN Always use [Link] for sustained forces (engines). Always use [Link]
G for instant hits (jumps, explosions). Mixing them up is the #1 bug in beginner physics code.
2.3 AddForceAtPosi�on — The Key to Realis�c Torque
Regular AddForce applies force at the center of mass — no rota�on. AddForceAtPosi�on applies force at a
specific world point, crea�ng both linear accelera�on AND torque propor�onal to how far the point is from the
center of mass. This is how suspension, wheel drive, and lateral grip create realis�c body roll.
// Force at center of mass — pure acceleration, no rotation
[Link]([Link] * 5000f, [Link]);
// Force at a wheel contact — acceleration + body roll
[Link]([Link] * 5000f, wheelContactPoint, [Link]);
Page 7
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
// ↑ This creates a torque = 5000 × distance_from_CoM
// Front wheel hit → car pitches forward
// Side wheel hit → car rolls to that side
// GetPointVelocity — velocity of a SPECIFIC POINT on the body
// Essential for suspension damping and per-wheel grip
Vector3 wheelVelocity = [Link](wheelContactPoint);
float verticalVelocity = [Link](wheelVelocity, [Link]);
2.4 Physics Materials
A Physics Material on a Collider controls fric�on and bounciness when two objects touch.
Property Effect
Dynamic Fric�on Fric�on while sliding. 0 = ice, 0.6 = rubber on tarmac, 1 = very grippy.
Sta�c Fric�on Fric�on before star�ng to slide. Usually higher than dynamic.
Bounciness 0 = no bounce, 1 = perfect elas�c bounce. Use 0 for vehicles, 0.3 for balls.
Fric�on Combine How two materials combine. Maximum = most fric�on, Minimum = least.
Bounce Combine Same, for bounciness. Maximum for trampolines.
For vehicle wheels, use a Physics Material with dynamic fric�on 0.8, sta�c fric�on 1.0,
TIP
bounciness 0. This ensures the collider doesn't bounce or slide on contact.
2.5 Layer-Based Collision
Physics Layers let you control which objects collide with which. Cri�cal for raycasts — you don't want a car's
raycast to hit its own body.
// Common layer setup for vehicle physics:
// Layer 0: Default
// Layer 8: Ground (terrain, roads, ramps)
// Layer 9: Vehicle (car bodies)
// Layer 10: Wheel (wheel colliders)
// Raycast that ONLY hits Ground layer:
int groundLayer = [Link]("Ground");
[Link](origin, [Link], out hit, maxDist, groundLayer);
Page 8
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
// Raycast that hits everything EXCEPT the vehicle itself:
int mask = ~[Link]("Vehicle");
[Link](origin, [Link], out hit, maxDist, mask);
// The ~ operator INVERTS the mask (everything except those layers)
Page 9
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
CH
Raycasts & Spa�al Queries
3 The Swiss Army Knife of Physics Systems
Raycasts are how your physics code perceives the world. Ground detec�on, surface normals, obstacle avoidance,
ramp detec�on — they all use raycasts. Master these and 80% of physics problems become solvable.
3.1 Raycast Fundamentals
// Basic raycast — returns true if something was hit
RaycastHit hit;
if ([Link](origin, direction, out hit, maxDistance, layerMask))
{
// [Link] — world position of the hit
// [Link] — surface normal at hit point (perpendicular to surface)
// [Link] — how far the ray travelled
// [Link] — the collider that was hit
// [Link] — transform of the hit object
}
// Sphere cast — like raycast but with radius (useful for wheels)
if ([Link](origin, radius, direction, out hit, maxDistance, mask))
{
// Useful when a point-ray misses thin ramps or edges
}
// Box cast — sweep a box through space
[Link](center, halfExtents, direction, out hit, rotation, maxDist, mask);
// OverlapSphere — find all colliders within a radius (explosions!)
Collider[] nearby = [Link](position, radius, mask);
// Visualize in Scene view (extremely useful for debugging):
[Link](origin, direction * maxDistance, [Link]);
[Link](origin, [Link], [Link]);
[Link]([Link], [Link] * 0.5f, [Link]); // surface normal
3.2 Surface Normals — Reading the Ground
The [Link] is a unit vector poin�ng perpendicular (outward from) the surface. This is how you detect slopes,
ramps, and walls versus floors.
// Detect surface angle (degrees from flat horizontal):
float angle = [Link]([Link], [Link]);
// angle == 0 → perfectly flat ground
// angle == 45 → 45-degree slope
Page 10
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
// angle == 90 → vertical wall
// angle == 180 → ceiling
bool isGround = angle < 45f; // walkable floor
bool isSlope = angle >= 45f && angle < 80f;
bool isWall = angle >= 80f;
// Align car body to slope (visual mesh matching terrain):
Quaternion targetRot = [Link]([Link], [Link])
* [Link];
[Link] = [Link]([Link], targetRot, speed * dt);
// Calculate actual forward direction along a slope:
Vector3 slopeForward = [Link]([Link], [Link]).normalized;
[Link](slopeForward * engineForce, [Link]);
3.3 The Four-Corner Raycast Pa�ern
This is the suspension raycast pa�ern used in the car controller. It detects ground at each wheel independently,
enabling realis�c body roll and individual wheel behavior.
// Define anchor offsets (local space, relative to car center)
Vector3[] corners = {
new Vector3(-0.75f, 0f, 1.3f), // Front-Left
new Vector3( 0.75f, 0f, 1.3f), // Front-Right
new Vector3(-0.75f, 0f, -1.3f), // Rear-Left
new Vector3( 0.75f, 0f, -1.3f), // Rear-Right
};
int groundCount = 0;
foreach (var localOffset in corners)
{
// Convert local offset to world position
Vector3 worldOrigin = [Link](localOffset);
if ([Link](worldOrigin, [Link], out RaycastHit hit,
suspLength + wheelRadius, groundMask))
{
groundCount++;
float extend = [Link] - wheelRadius;
float compression = 1f - (extend / suspLength);
// Use compression to calculate spring force...
}
}
bool isGrounded = groundCount >= 2;
Page 11
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
CH
Spring & Suspension Systems
4 Hooke's Law · Dampers · Cri�cal Damping
The spring-damper system is the single most reusable physics component you'll build. It appears in car
suspension, helicopter hovering, camera springs, rope simula�on, and cloth. Learn it once, use it everywhere.
4.1 Hooke's Law — Spring Force
F_spring = -k × x
Where k is spring s�ffness (N/m) and x is displacement from rest posi�on. The nega�ve sign means it always
pushes back toward rest. In suspension, x is how much the spring is compressed.
// Spring compression from raycast:
float restLength = suspensionLength; // target hover height
float currentLength = [Link] - wheelRadius; // actual extension
float compression = restLength - currentLength; // positive = compressed
// Spring force — pushes car up when spring is compressed
float springForce = compression * springStiffness;
// Apply upward — positive compression = push up
if (springForce > 0f)
[Link]([Link] * springForce, [Link], [Link]);
4.2 The Damper — Killing Oscilla�on
A spring without damping bounces forever. A damper adds a force propor�onal to velocity that opposes mo�on.
Think of it like thick oil inside a shock absorber.
F_damper = -c × v
Where c is the damping coefficient and v is the velocity of compression/extension. Combined spring + damper:
F_total = k × x - c × v
// Get velocity at wheel contact point
Vector3 contactVel = [Link]([Link]);
// Project onto suspension axis (car's up direction)
float velAlongSpring = [Link](contactVel, [Link]);
// Damper opposes upward velocity
Page 12
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
// If car is moving up fast (spring extending), damper resists
// If car is moving down fast (spring compressing), damper resists
float damperForce = velAlongSpring * springDamper;
// Combined force
float totalForce = [Link](0f, compression * springStiffness - damperForce);
[Link]([Link] * totalForce, [Link], [Link]);
4.3 Cri�cal Damping — No Bounce
Underdamped = bouncy (suspension oscillates). Overdamped = sluggish (takes long to reach rest). Cri�cally
damped = se�les to rest as fast as possible without bouncing. This is the target for most vehicle suspension.
Critical Damper = 2 × √(spring_stiffness × mass)
// Calculate critical damping for a vehicle wheel:
// Each wheel supports roughly 1/4 of the car mass
float wheelMass = [Link] / 4f;
float criticalDamper = 2f * [Link](springStiffness * wheelMass);
// Use 0.7–0.9 × critical for slightly bouncy sports car
// Use 1.0 × critical for smooth luxury car feel
// Use 1.2 × critical for monster truck (slow settling)
float actualDamper = criticalDamper * 0.8f; // slightly underdamped
// Practical starting values for a 1400kg car with 4 wheels:
// springStiffness = 30000
// criticalDamper ≈ 2 × sqrt(30000 × 350) ≈ 6480
// Use ~4000 for sportier feel
The formula for cri�cal damping is the most important tuning formula in vehicle physics. If
KEY
your suspension is bouncing, increase the damper. If it's too sluggish, reduce it.
4.4 Reusable Spring Class — Modular Pa�ern
// Reusable spring component — attach to any Rigidbody system
[[Link]]
public class SpringDamper
{
public float stiffness = 30000f;
public float damping = 4000f;
public float restLength = 0.5f;
// Returns force to apply (positive = push toward anchor)
public float Evaluate(float currentLength, float extensionVelocity)
{
float compression = restLength - currentLength;
float springF = compression * stiffness;
float damperF = extensionVelocity * damping;
return [Link](0f, springF - damperF);
Page 13
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
}
}
// Use it anywhere:
// In car: SpringDamper[] wheelSprings = new SpringDamper[4];
// In helicopter: SpringDamper hoverSpring;
// In camera: SpringDamper followSpring;
Page 14
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
CH
Vehicle Physics — Bikes & Hovercra�s
5 Two-Wheel Balance · Lean Steering · Hover Cushions
The car controller has been covered in detail. This chapter focuses on the physics that make bikes and hovercra�s
unique — systems you can combine and adapt.
5.1 Bike Physics — The Lean-Balance Problem
A bike has two main physics challenges: it falls over without forward mo�on, and it steers by leaning not just
turning. Both require ac�ve physics correc�on.
The Lean-to-Steer Connec�on
In reality, you steer a bike by leaning. The controller should automa�cally apply lean torque when the bike turns,
and the lean should drive the turn. This creates the organic, linked feel of real bike riding.
// BIKE CONTROLLER — core physics methods
// 1. Balance: apply torque to keep bike upright when moving
void ApplyBalance()
{
// Current lean angle from vertical
float leanAngle = [Link]([Link], [Link],
[Link]);
float speed = [Link];
// Gyroscopic stability — faster = more self-stable
float gyroFactor = Mathf.Clamp01(speed / 5f);
float balanceTorque = -leanAngle * balanceStrength * gyroFactor;
// Apply along forward axis (roll correction)
[Link]([Link] * balanceTorque, [Link]);
}
// 2. Lean into turns
void ApplyLeanSteering(float steerInput)
{
float speed = [Link];
float targetLean = -steerInput * maxLeanAngle
* Mathf.Clamp01(speed / fullLeanSpeed);
// Current lean
float currentLean = [Link]([Link], [Link],
[Link]);
float leanError = targetLean - currentLean;
Page 15
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
// Lean torque — rolls bike into turn
[Link]([Link] * leanError * leanTorque, [Link]);
// Yaw torque — proportional to lean angle (lean drives turn)
float actualLean = currentLean;
float yawTorque = actualLean * -leanToYawRatio;
[Link]([Link] * yawTorque, [Link]);
}
Bike Stability vs. Speed Diagram
State Physics Behavior
Speed: 0-2 m/s No gyro stabiliza�on. Use AddForce on ground contact to prevent falling.
Speed: 2-8 m/s Par�al stabiliza�on. Lean-to-steer engages gradually.
Speed: 8+ m/s Full gyro. Lean drives steering. Balance is mostly self-correc�ng.
Airborne Disable balance. Allow lean control for style tricks. Auto-level on landing.
5.2 Hovercra� Physics — Cushion of Air
A hovercra� floats on a cushion of compressed air. The physics model: constantly cast rays downward, apply
upward spring forces to maintain hover height, and use a strong lateral drag to prevent infinite sliding (the
hovercra� skirt effect).
// HOVERCRAFT — complete core physics
void FixedUpdate()
{
ApplyHoverForce();
ApplyHoverDrag(); // skirt friction
ApplyThrustAndTurn();
}
void ApplyHoverForce()
{
// Four-point hover suspension (same as car wheel raycasts)
foreach (var point in hoverPoints)
{
Vector3 origin = [Link](point);
if ([Link](origin, -[Link], out var hit, hoverHeight * 1.5f))
{
float compression = 1f - ([Link] / hoverHeight);
float upVel = [Link]([Link]([Link]), [Link]);
float force = [Link](0f,
compression * hoverSpring - upVel * hoverDamper);
Page 16
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
[Link]([Link] * force, [Link], [Link]);
}
}
}
void ApplyHoverDrag()
{
// Air cushion resists sideways and forward movement
// This is what makes hovercrafts feel floaty but not infinite-sliding
float lateralVel = [Link]([Link], [Link]);
float forwardVel = [Link]([Link], [Link]);
// Skirt has much more lateral drag than forward drag
[Link](-[Link] * lateralVel * lateralDrag, [Link]);
[Link](-[Link] * forwardVel * forwardDrag, [Link]);
}
Page 17
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
CH
Helicopter Physics
6 Li� · Torque Reac�on · Cyclic · Collec�ve · Tail Rotor
Helicopters are one of the best physics playgrounds because every axis of control is separate and physically
dis�nct. Understanding real helicopter controls makes the code elegant.
6.1 How a Real Helicopter Flies
Control Physics Effect
Collec�ve All rotor blades pitch up equally → more li�. Thro�le equivalent.
Cyclic (Pitch) Blades pitch more at back → helicopter �lts forward → moves forward.
Cyclic (Roll) Blades pitch more at one side → helicopter �lts sideways → moves
sideways.
Tail Rotor Counteracts main rotor torque reac�on. Yaw control.
Torque Reac�on Main rotor spinning clockwise → fuselage wants to spin counter-clockwise.
6.2 Complete Helicopter Controller
// HELICOPTER PHYSICS — modular implementation
// Each method maps to one real helicopter control
public float lift = 15000f; // base lift force
public float cyclicForce = 8000f; // tilt-to-move force
public float tailRotorForce = 5000f; // yaw torque
public float rotorTorque = 3000f; // torque reaction
public float hoverDamping = 5f; // vertical damping
public float tiltLimit = 30f; // max tilt degrees
void FixedUpdate()
{
float collective = [Link]("Vertical"); // W/S = up/down
float cyclicX = [Link]("Horizontal"); // A/D = roll
float cyclicZ = [Link]("Mouse Y"); // Mouse = pitch
float tail = [Link]("Mouse X"); // Mouse X = yaw
ApplyCollective(collective);
Page 18
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
ApplyCyclic(cyclicX, cyclicZ);
ApplyTailRotor(tail);
ApplyTorqueReaction();
ApplyVerticalDamping();
LimitTilt();
}
// COLLECTIVE — main lift control
void ApplyCollective(float input)
{
// Base lift to hover + pilot input
float hoverForce = [Link] * [Link]([Link].y);
float totalLift = hoverForce + input * lift;
[Link]([Link] * totalLift, [Link]);
}
// CYCLIC — tilt to move (helicopter goes where its top points)
void ApplyCyclic(float roll, float pitch)
{
// Tilt the helicopter
[Link]([Link] * roll * cyclicForce, [Link]);
[Link]([Link] * -pitch * cyclicForce, [Link]);
// Movement comes from lift vector tilting with the body
// [Link] points in helicopter's local up direction
// When tilted, this becomes partly forward — gives movement
// (This happens automatically! The lift force + tilt = movement)
}
// TAIL ROTOR — yaw control
void ApplyTailRotor(float input)
{
[Link]([Link] * input * tailRotorForce, [Link]);
}
// TORQUE REACTION — rotor spins, body wants to spin opposite
void ApplyTorqueReaction()
{
float throttle = ...; // get collective input
// Main rotor spins CW → torque reaction is CCW (negative Y)
[Link](-[Link] * throttle * rotorTorque, [Link]);
}
// VERTICAL DAMPING — kill oscillation on Y axis
void ApplyVerticalDamping()
{
float vertVel = [Link]([Link], [Link]);
[Link](-[Link] * vertVel * hoverDamping, [Link]);
}
// TILT LIMITER — prevents flipping (arcade feel)
void LimitTilt()
{
float tilt = [Link]([Link], [Link]);
if (tilt > tiltLimit)
{
Vector3 corrAxis = [Link]([Link], [Link]);
float corrAmount = (tilt - tiltLimit) * 500f;
[Link](corrAxis * corrAmount, [Link]);
}
}
Page 19
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
The elegant secret: you never explicitly add horizontal movement force in a helicopter
KEY controller. Tilt the body → the li� vector �lts with it → the horizontal component of that li� IS
the movement force. This is physically accurate and requires zero extra code.
Page 20
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
CH
Ragdoll & Joint Systems
7 ConfigurableJoint · Ar�cula�on Bodies · Ac�ve Ragdoll
Ragdolls are a chain of rigid bodies connected by joints. The physics engine solves joint constraints to keep the
body together while gravity and collisions do the rest.
7.1 Ragdoll Anatomy
Component Details
Rigidbody on each bone Hip, spine, chest, head, upper arms, forearms, thighs, shins, feet
Collider on each bone Capsules for limbs, Box for chest/hip, Sphere for head
CharacterJoint / Connects each bone to its parent with angle limits
ConfigurableJoint
Mass distribu�on Hip ~30%, chest ~20%, head ~8%, each limb ~5-8%
7.2 Joint Types
Joint Type Best For
HingeJoint Single axis rota�on. Elbows, knees. Simple and stable.
CharacterJoint Ball and socket with twist and swing limits. Built for ragdolls.
ConfigurableJoint Complete control. All axes configurable. Complex but powerful.
FixedJoint Rigid connec�on. No rela�ve movement. Good for a�aching held objects.
SpringJoint Elas�c connec�on. Returns to rest distance. Good for ropes, tentacles.
Page 21
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
7.3 Programma�c Ragdoll — No Editor Required
// Build a simple arm ragdoll in code
public Rigidbody CreateRagdollChain()
{
// 1. Upper arm
var upperArm = CreateBone("UpperArm", new Vector3(0, 0, 0), mass: 2f);
var capsule = [Link]<CapsuleCollider>();
[Link] = 0.35f; [Link] = 0.06f;
// 2. Forearm (child of upperArm)
var foreArm = CreateBone("ForeArm", new Vector3(0, -0.35f, 0), mass: 1.5f);
// 3. Connect with HingeJoint
var hinge = [Link]<HingeJoint>();
[Link] = foreArm;
[Link] = new Vector3(1, 0, 0); // rotate around X
[Link] = new JointLimits { min = -10f, max = 140f }; // elbow angles
[Link] = true;
return upperArm;
}
Rigidbody CreateBone(string name, Vector3 localPos, float mass)
{
var go = new GameObject(name);
[Link] = localPos;
var rb = [Link]<Rigidbody>();
[Link] = mass;
[Link] = 12;
return rb;
}
7.4 Ac�ve Ragdoll (Procedural Anima�on)
An ac�ve ragdoll uses PD controllers (Propor�onal-Deriva�ve) to apply torques to each joint, trying to match a
target pose. The result looks animated but reacts to physics forces naturally.
// PD Controller for a single joint — drives joint to target rotation
[[Link]]
public class PDController
{
public float spring = 1000f; // P gain — how hard to reach target
public float damper = 50f; // D gain — how much to slow down
public void Apply(Rigidbody rb, Quaternion targetLocalRot,
Quaternion currentLocalRot, Vector3 currentAngVel,
float deltaTime)
{
// Error: rotation needed to reach target
Quaternion rotError = targetLocalRot * [Link](currentLocalRot);
[Link](out float angle, out Vector3 axis);
if (angle > 180f) angle -= 360f;
// PD torque: spring drives toward target, damper kills overshoot
Page 22
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
Vector3 torque = axis * (angle * Mathf.Deg2Rad * spring)
- currentAngVel * damper;
[Link](torque, [Link]);
}
}
// In each bone's FixedUpdate:
// [Link](rb, [Link], [Link],
// [Link], [Link]);
Page 23
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
CH
Physics Simula�ons
8 Projec�les · Explosions · Cloth · Water Buoyancy
These systems combine the founda�onal concepts into complete simula�ons you can drop into any project.
8.1 Projec�le Physics — Predict the Trajectory
// Predict projectile landing point (no air resistance)
// Uses kinematic equations: position = p0 + v0*t + 0.5*g*t²
Vector3 PredictLanding(Vector3 startPos, Vector3 startVel, int steps = 60)
{
Vector3 pos = startPos;
Vector3 vel = startVel;
float dt = 0.05f; // prediction step size
for (int i = 0; i < steps; i++)
{
vel += [Link] * dt;
pos += vel * dt;
// Check if we hit something
if ([Link](pos, [Link], out var hit, [Link] * dt))
return [Link];
}
return pos;
}
// Calculate launch velocity to hit a target:
bool CalculateLaunchVelocity(Vector3 from, Vector3 to, float speed,
out Vector3 velocity)
{
Vector3 dir = to - from;
float h = dir.y;
dir.y = 0;
float dist = [Link];
float g = -[Link].y;
float s2 = speed * speed;
float discriminant = s2 * s2 - g * (g * dist * dist + 2 * h * s2);
if (discriminant < 0) { velocity = [Link]; return false; }
float angle = [Link]((s2 - [Link](discriminant)) / (g * dist));
velocity = [Link] * speed * [Link](angle)
+ [Link] * speed * [Link](angle);
return true;
}
8.2 Explosion Physics
Page 24
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
// Sphere explosion — push all rigidbodies within radius
void Explode(Vector3 center, float radius, float force)
{
// Find all colliders within explosion radius
Collider[] hits = [Link](center, radius);
foreach (var col in hits)
{
var rb = [Link]<Rigidbody>();
if (rb == null) continue;
// Direction from explosion to object
Vector3 direction = ([Link] - center).normalized;
// Force falls off with distance squared (inverse square law)
float distance = [Link]([Link], center);
float falloff = 1f - Mathf.Clamp01(distance / radius);
float scaledForce = force * falloff * falloff; // quadratic falloff
// AddExplosionForce handles the calculation automatically:
[Link](scaledForce, center, radius, 0.5f,
[Link]);
// 0.5f = upward modifier (gives realistic upward throw)
}
}
// Custom directional blast (shaped explosion):
void DirectionalBlast(Vector3 origin, Vector3 direction, float radius, float force)
{
Collider[] hits = [Link](origin, radius);
foreach (var col in hits)
{
var rb = [Link]<Rigidbody>();
if (rb == null) continue;
// Only affect objects in the blast direction
Vector3 toObj = ([Link] - origin).normalized;
float dot = [Link](direction, toObj); // -1 to 1
if (dot < 0) continue; // behind the blast, skip
[Link](toObj * force * dot, [Link]);
}
}
8.3 Simple Buoyancy Physics
// Buoyancy: objects float when submerged below a water surface
// Archimedes: buoyant force = density_water × volume_submerged × gravity
public class BuoyancyPoint : MonoBehaviour
{
public float waterLevel = 0f; // world Y of water surface
public float buoyancyForce = 25f; // force per point when submerged
public float waterDrag = 3f; // velocity damping in water
public Transform[] floatPoints; // points on the object hull
Rigidbody rb;
Page 25
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
void Awake() => rb = GetComponent<Rigidbody>();
void FixedUpdate()
{
foreach (var pt in floatPoints)
{
float submergeDepth = waterLevel - [Link].y;
if (submergeDepth > 0)
{
// Deeper = more buoyancy (clamped to 1 point height)
float clampedDepth = [Link](submergeDepth, 0f, 1f);
// Upward force at contact point
float upForce = clampedDepth * buoyancyForce * [Link];
[Link]([Link] * upForce, [Link],
[Link]);
// Water drag — slows movement in water
[Link](-[Link] * waterDrag, [Link]);
}
}
}
}
Page 26
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
CH
Modular Physics Architecture
9 Interfaces · ScriptableObjects · Component Composi�on
The difference between a physics controller that works and one that's extensible is architecture. This chapter
shows you how to structure physics systems so they're reusable, testable, and easy to extend.
9.1 The Core Principle: Separate Data from Behavior
Physics parameters (spring strength, drag values, max speed) are data. Physics calcula�ons (applying spring force,
calcula�ng grip) are behavior. Keep them separate.
// DATA — ScriptableObject (assets, drag into any vehicle)
[CreateAssetMenu(fileName = "CarStats", menuName = "Physics/Car Stats")]
public class CarStats : ScriptableObject
{
[Header("Suspension")]
public float springStrength = 30000f;
public float springDamper = 4000f;
public float suspensionLength = 0.5f;
[Header("Engine")]
public float engineForce = 5500f;
public float topSpeed = 36f;
[Header("Steering")]
public float steerTorque = 4500f;
public float steerMinSpeed = 1.5f;
}
// BEHAVIOR — pure calculation, no state
public static class SuspensionSystem
{
public static float Calculate(float compression, float velAlongSpring,
CarStats stats)
{
float springF = compression * [Link];
float damperF = velAlongSpring * [Link];
return [Link](0f, springF - damperF);
}
}
// CONTROLLER — uses data + behavior
public class CarController : MonoBehaviour
{
public CarStats stats; // drag in any preset from Project window
void ApplySuspension(Wheel w)
{
float velAlongSpring = [Link](
Page 27
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
[Link]([Link]), [Link]);
float force = [Link](
[Link], velAlongSpring, stats);
[Link]([Link] * force, [Link],
[Link]);
}
}
9.2 Interface-Based Physics Components
Use interfaces to allow swapping physics behaviors. A helicopter and a hovercra� both need 'hover' but
implement it differently. An interface lets the controller not care about the details.
// Interface definitions
public interface ILiftProvider
{
void ApplyLift(Rigidbody rb, float input);
}
public interface ISteeringProvider
{
void ApplySteering(Rigidbody rb, float input, float speed);
}
// Implementations
public class RotorLift : MonoBehaviour, ILiftProvider
{
public float liftForce = 15000f;
public void ApplyLift(Rigidbody rb, float input)
{
float hover = [Link] * [Link]([Link].y);
[Link]([Link] * (hover + input * liftForce), [Link]);
}
}
public class SpringLift : MonoBehaviour, ILiftProvider
{
public SpringDamper spring;
public void ApplyLift(Rigidbody rb, float input)
{
// ... raycast-based spring lift
}
}
// Controller — works with ANY lift implementation
public class VehicleController : MonoBehaviour
{
ILiftProvider lift;
ISteeringProvider steering;
void Awake()
{
lift = GetComponent<ILiftProvider>();
steering = GetComponent<ISteeringProvider>();
}
Page 28
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
void FixedUpdate()
{
[Link](rb, throttleInput);
[Link](rb, steerInput, Speed);
}
}
9.3 Universal Physics Component Checklist
Every physics system you build should answer these ques�ons before you write a line of code:
1. What Rigidbody(s) does this system affect?
2. What are the inputs? (Player input, AI commands, environment queries)
3. What forces/torques are applied, where, and in what mode?
4. What are the tuning parameters? (Should they be ScriptableObjects?)
5. What is the grounding/state condi�on? (When does each force apply?)
6. How will you debug it? (What [Link] lines will you need?)
7. What is the failure mode? (What happens if the raycast misses?)
Page 29
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
CH
Debugging, Tuning & Performance
10 Gizmos · Time Scale · Physics Profiler · Common Bugs
The gap between a physics system that 'sort of works' and one that feels polished is almost always debugging
and tuning. These tools and techniques will save you enormous �me.
10.1 Essen�al Debug Visualiza�on
// Put all physics debug visualization in OnDrawGizmos
// (runs in Scene view even when not playing)
void OnDrawGizmosSelected()
{
// Draw wheel rays
[Link] = [Link];
foreach (var anchor in wheelAnchors)
{
[Link]([Link], wheelRadius);
[Link]([Link],
[Link] - [Link] * suspensionLength);
}
// Draw center of mass
if (rb != null)
{
[Link] = [Link];
[Link]([Link]([Link]), 0.15f);
}
}
// In FixedUpdate — runtime force visualization
void FixedUpdate()
{
// Draw suspension compression (green=compressed, yellow=light, grey=air)
[Link]([Link], -[Link] * suspensionLength,
[Link] ? ([Link] > 0.5f ? [Link] : [Link])
: [Link]);
// Draw applied forces as arrows
[Link]([Link], [Link] * (force / [Link]), [Link]);
// Draw velocity vector
[Link]([Link], [Link] * 0.1f, [Link]);
}
10.2 Time Scale Debugging
// Slow motion debugging — add to any controller
Page 30
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
void Update()
{
// Hold Tab to slow time to 10%
if ([Link]([Link]))
[Link] = [Link]([Link]) ? 0.1f : 1.0f;
if ([Link]([Link]))
[Link] = 1.0f;
// Frame-by-frame: press Space to advance one physics step
if ([Link] == 0f && [Link]([Link]))
{
[Link] = 0.01f;
Invoke(nameof(PauseAgain), [Link]);
}
}
void PauseAgain() => [Link] = 0f;
10.3 Common Physics Bugs & Fixes
Bug Fix
Object ji�ers on ground Raise [Link]�ons to 12. Check if two springs are figh�ng. Use
velocity-dot damping, not compression-delta damping.
Object rotates when sta�onary Speed gate on steering. Check steerMinSpeed. Ensure no lateral force fires
at zero velocity.
Object tunnels through thin Set CollisionDetec�on to Con�nuousDynamic. Raise fixedDeltaTime rate in
surfaces Project Se�ngs.
Suspension bounces forever Damper too low. Raise springDamper. Recalculate using cri�cal damping
formula.
Forces feel inconsistent at You're using Update() for forces. Move ALL AddForce calls to
different frame rates FixedUpdate().
Raycast hits own collider Use layer mask excluding own layer. ~[Link]('Vehicle').
Angular velocity explodes Clamp angularVelocity per axis in FixedUpdate. Set angularDamping higher.
AddForceAtPosi�on causes Apply force along world-up, not local-up, if the car is �lted. Or normalize
phantom torque force direc�on.
Page 31
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
10.4 Performance — Physics is Expensive
Area Op�miza�on
Raycasts Cache results — don't raycast the same ray twice per frame. Use
BatchRaycasts for mul�ple.
OverlapSphere Expensive. Only run on events, not every frame. Cache result array.
Fixed Timestep Lower value = more accurate but more CPU. Default 0.02 is fine. 0.01 for
high-fidelity sim.
[Link] Objects that don't move go to sleep (no simula�on). Avoid waking them
unnecessarily.
Collider complexity Mesh colliders are expensive. Use Primi�ve colliders (box, sphere, capsule)
for physics objects.
10.5 The Tuning Workflow
Follow this order when tuning any physics system:
8. Fix stability first: no ji�er, no phantom forces, correct sleep behavior.
9. Tune suspension/hover: get the object res�ng at the correct height without bouncing.
10. Tune mass and base forces: object should accelerate at the intended rate.
11. Tune drag: object should reach intended top speed and stop within intended distance.
12. Tune steering/rota�on: feels responsive at low speed, controlled at high speed.
13. Tune grip/slide balance: the fun window between control and dri�.
14. Final pass: body roll, visual polish, sound hook points (IsGrounded, Speed, etc).
Always test at extreme values first. Set engineForce to 100x, watch what breaks. Then bring it
TIP
back. Edge cases reveal architecture bugs that normal values hide.
10.6 Quick Reference — Unity Physics API
Page 32
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
Method / Property Purpose
[Link](v, mode) Apply force to center of mass
[Link]�on(v, p, Apply force at world point (creates torque)
mode)
[Link](v, mode) Apply rota�onal force
[Link]�veForce(v, mode) Force in local space
[Link](p) Velocity of a specific world point on the body
[Link] Current world-space velocity
[Link] Current rota�on speed (radians/sec)
[Link] Set to override calculated CoM
[Link] Object mass in kilograms
[Link] Linear drag coefficient
[Link] Angular drag coefficient
[Link](orig, dir, out hit, Cast a ray, return first hit
dist, mask)
[Link](...) Cast a sphere (be�er for edges/slopes)
[Link](p, r, Find all colliders within radius
mask)
[Link] Current gravity vector (default 0,-9.81,0)
[Link](a, b) How aligned two direc�ons are (-1 to 1)
[Link](a, b) Perpendicular vector (rota�on axis)
[Link](v, n) Remove component along normal n
Page 33
UNITY PHYSICS SYSTEMS HANDBOOK | From Founda�ons to Arcade Controllers
Method / Property Purpose
[Link]�on(a, Rota�on to go from direc�on a to b
b)
[Link](local) Convert local offset to world posi�on
[Link] Convert world direc�on to local
�on(world)
You now have everything you need to build any arcade physics system from scratch.
Page 34