en-unity-physics-3d-guide

⚙️ Physics in Unity 3D

A comprehensive guide to the physics system in Unity 6: components, mechanisms, and best practices for creating realistic simulations.

🎮 Introduction to the Unity Physics System

Unity's physics system is a simulation engine based on PhysX, which calculates realistic interactions between objects in the 3D world. Without adding code, an object with a Rigidbody will be attracted by gravity and react to collisions.

💡 Key Fact: The PhysX engine is used by the professional video game industry. It is optimized for CPU/GPU and produces predictable, consistent results.

Why does physics matter?

  • Realism: Objects move in a believable and predictable way
  • Gameplay: Game mechanics depend on physics (jumps, collisions, gravity)
  • Optimization: PhysX is highly optimized for production
  • Control: You can adjust every aspect for your specific game
⚠️ Technical Note: Physics in Unity is calculated at fixed intervals (Fixed Timestep) typically of 0.02 seconds. This is independent of the render FPS.

🔧 Main Components of the Physics System

For physics to work in Unity you need at least two components working together:

📦 Rigidbody

Function: Controls the movement and physics of a GameObject.

Requires: A Collider to interact.

Key properties:

  • Mass
  • Drag (Air resistance)
  • Angular Drag (Rotational resistance)
  • Gravity (Affected by gravity)
  • Constraints
⚡ Collider

Function: Defines the shape of the object to detect collisions.

Types: Box, Sphere, Capsule, Mesh, Wheel, Terrain.

Key properties:

  • Is Trigger
  • Material (Physics Material)
  • Offset
  • Size

Rigidbody States

State Description Use Cases
Dynamic Full physics simulation. Affected by forces and collisions. Moving objects (balls, boxes, enemies)
Kinematic Moved by scripts, but dynamic objects bounce off it. Moving platforms, doors
Static Does not move. More efficient than dynamic. Floors, walls, fixed obstacles

📐 Types of Colliders in Unity 3D

Each type of collider is optimized for different shapes and use cases:

Primitive
📦 Box Collider

Shape: Cube/Rectangle.

Use: Boxes, walls, platforms.

Advantage: Very fast, ideal for simple geometric objects.

CPU: ⭐⭐⭐ | Precision: ⭐⭐⭐

Primitive
🟢 Sphere Collider

Shape: Sphere.

Use: Balls, explosions, projectiles.

Advantage: Perfect for distance calculations and spherical detection.

CPU: ⭐⭐⭐ | Precision: ⭐⭐

Primitive
🔷 Capsule Collider

Shape: Cylinder with hemispheres.

Use: Characters, humanoid enemies.

Advantage: Excellent for movement without getting stuck in corners.

CPU: ⭐⭐⭐ | Precision: ⭐⭐⭐

Advanced
🧩 Mesh Collider

Shape: Exact geometry of the 3D model.

Use: Complex terrains, scenarios.

Warning: More expensive. Use sparingly.

CPU: ⭐ | Precision: ⭐⭐⭐⭐⭐

Specialized
🎡 Wheel Collider

Shape: Specialized wheel.

Use: Vehicles, cars, motorcycles.

Advantage: Realistic simulation of suspension and grip.

CPU: ⭐⭐ | Precision: ⭐⭐⭐⭐

Terrain
🗻 Terrain Collider

Shape: Height map.

Use: Wide terrains, mountains.

Advantage: Optimized for large areas.

CPU: ⭐⭐⭐ | Precision: ⭐⭐⭐

Compound Colliders

For complex objects, you can combine multiple primitive colliders on child objects:

GameObject Player
├─ Capsule Collider (body)
├─ Box Collider (arms)
└─ Sphere Collider (head)

Advantage: Greater precision than Mesh Collider, better performance than a single Mesh.

🎨 Physics Materials: Friction and Bounce

Physics Materials define how surfaces behave when they come into contact with other objects.

Main Properties

  • Dynamic Friction: Friction while sliding (0 = ice, 1 = sticky)
  • Static Friction: Friction at rest
  • Bounciness: Bounce (0 = no bounce, 1 = maximum bounce)
  • Friction Combine: How frictions are combined
  • Bounce Combine: How bounces are combined

Example Values

Material Friction Bounce
Ice 0.05 0.0
Asphalt 0.7 0.2
Tennis Ball 0.5 0.8
Rubber 1.0 0.3
Steel 0.4 0.9

Combination Modes

When two materials collide, they are combined using one of these modes:

Average

Average of both values. The most realistic.

Multiply

Multiplication. Results in lower values.

Minimum

Uses the smaller value (stickier/less bounce).

Maximum

Uses the larger value (slipperier/more bounce).

🔗 Joints: Constraints and Articulations

Joints connect two Rigidbodies and create constrained movement behaviours. They are essential for ragdolls, chains, and mechanisms.

📌 Fixed Joint

Behaviour: Rigidly fixes two Rigidbodies in their relative position.

Use: Joined objects, connected machine parts.

Important parameter: Breaking Force (force needed to break the joint).

// Fixed Joint in code
Rigidbody rb1 = obj1.GetComponent<Rigidbody>();
Rigidbody rb2 = obj2.GetComponent<Rigidbody>();
FixedJoint joint = obj1.AddComponent<FixedJoint>();
joint.connectedBody = rb2;
joint.breakForce = 1000f;
🎪 Spring Joint

Behaviour: Acts like an elastic spring between two Rigidbodies.

Use: Ropes, cables, vehicle suspensions.

Parameters:

  • Spring: Spring resistance (higher = stronger)
  • Damper: Damping (reduces oscillations)
  • Min/Max Distance: Rest distance
🔄 Hinge Joint

Behaviour: Allows rotation on one axis (like a door).

Use: Doors, mechanical arms, levers.

Configuration: Define the axis of rotation (X, Y, or Z) and rotation limits.

// Hinge Joint - Door
HingeJoint hinge = doorGameObject.AddComponent<HingeJoint>();
hinge.axis = Vector3.up; // Rotation on Y axis
hinge.limits = new JointLimits() {
    min = 0,
    max = 90,
    bounciness = 0
};
👤 Character Joint

Behaviour: Extended ball-and-socket joint for ragdolls.

Use: Ragdoll skeletons, human joints (arms, legs, neck).

Advantage: Allows complex rotation on multiple axes.

Parameters: Swing Limits (frontal rotation), Twist Limits (axial rotation).

⚙️ Configurable Joint

Behaviour: The most flexible joint. Configurable in all degrees of freedom.

Use: Custom behaviours, specialized joints.

Complexity: High. Allows locking/unlocking 6 degrees of freedom (3 rotations + 3 translations).

Note: More computationally expensive than other joints.

🎯 Ball Joint

Behaviour: Ball and socket like a hip joint.

Use: Spherical joints, hips, shoulders.

Feature: Allows rotation on all axes with specific limits.

💪 Applying Forces and Movement

There are multiple ways to move a Rigidbody. Each has its purpose:

⚡ AddForce()

Applies a continuous force that accumulates.

rigidbody.AddForce(Vector3.forward * 10);
// Gradually accelerates

Cases: Jumps, pushes, explosions.

🎯 Velocity

Sets the velocity directly.

rigidbody.velocity = Vector3.forward * 5;
// Instant velocity

Cases: Knockback, projectile movement.

🌪️ AddTorque()

Applies rotational force.

rigidbody.AddTorque(Vector3.right * 5);
// Gradual rotation

Cases: Spinning balls, rotating objects.

📍 MovePosition()

Interpolated kinematic movement.

rigidbody.MovePosition(transform.position + Vector3.forward);

Cases: Characters, moving platforms.

Force Modes

When using AddForce(), you can specify how the force is applied:

Force Mode Formula Use
Force (Default) acceleration = Force / Mass Real forces (wind, gravity, pushes)
Acceleration Pure acceleration regardless of mass When you want all objects to accelerate equally
Velocity Direct velocity change Smooth character movement
Impulse Applied in one frame Explosions, instant jumps
⚠️ Important: Always apply forces in FixedUpdate(), not in Update(). Physics runs in a separate Fixed Timestep.
void FixedUpdate() {
    rigidbody.AddForce(Vector3.forward * 10);
}

💥 Collision Detection

Unity offers three ways to detect collisions:

📞 OnCollisionEnter

Executes when two colliders start touching.

Requires: Both with Collider, at least one with Rigidbody.

void OnCollisionEnter(Collision collision) {
    Debug.Log("Collision!");
}
👀 OnTriggerEnter

Executes when an object enters a Trigger.

Requires: Collider with "Is Trigger" enabled.

void OnTriggerEnter(Collider collider) {
    Debug.Log("Entered!");
}
🎯 Physics.Raycast

Casts an invisible ray to detect collisions.

Use: Weapons, AI vision, terrain.

RaycastHit hit;
if (Physics.Raycast(pos, dir, out hit)) {
    Debug.Log(hit.collider.name);
}

Collision Detection Methods

The Rigidbody has options to detect collisions in different ways:

📊 Discrete (Default)
Detects collisions by checking position each frame. Faster, but can fail with very fast objects.
📏 Continuous
Calculates the full trajectory. Detects all collisions, slower.

⚡ Optimizing the Physics System

Physics can be expensive. Here are the best practices to optimize:

1️⃣ Use Primitive Colliders

❌ Avoid: Mesh Colliders for dynamic objects.

✅ Do: Use Box, Sphere, Capsule Colliders.

Primitive colliders are 10-100x faster.

2️⃣ Mark static objects

❌ Avoid: Dynamic Rigidbody for objects that don't move.

✅ Do: Leave as Static or use Kinematic only when necessary.

Static objects are not recalculated every frame.

3️⃣ Use Layers and Collision Matrix

In Edit > Project Settings > Physics:

  • Define which layers can collide with each other
  • Example: Enemies don't need to collide with Enemies
  • Reduces unnecessary calculations
4️⃣ Compound Colliders

For complex objects:

  • Use multiple primitive colliders on child objects
  • Better than a single Mesh Collider
  • Faster + better precision
5️⃣ Limit Dynamic Rigidbodies

Each dynamic Rigidbody costs CPU:

  • Limit the number in scene (max ~100 at 60 FPS)
  • Use Kinematic for objects that don't need full physics
  • Destroy/Pool objects when possible
6️⃣ Adjust Fixed Timestep

In Edit > Project Settings > Time:

  • Fixed Timestep: Default 0.02s (50 FPS)
  • Increase to 0.03s-0.05s for less precise games
  • Reduces FixedUpdate() calls
7️⃣ Use Constraints

Freeze unnecessary axes:

  • 2D character: Freeze Z and rotations
  • Object that doesn't rotate: Freeze all rotations
  • Reduces math calculations
💡 Pro Tip: Use Unity Profiler (Window > Analysis > Profiler) to measure physics cost. Look for "Physics" in the Profiler tab.

🎮 Practical Examples

Example 1: Character Movement

// Character with jump
public class PlayerController : MonoBehaviour {
    private Rigidbody rb;
    public float moveSpeed = 5f;
    public float jumpForce = 5f;

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

    void FixedUpdate() {
        // Horizontal movement
        float x = Input.GetAxis("Horizontal");
        rb.velocity = new Vector3(x * moveSpeed, rb.velocity.y, 0);

        // Jump
        if (Input.GetKeyDown(KeyCode.Space)) {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
        }
    }
}

Example 2: Realistic Car Physics

// Suspension and traction
public class CarPhysics : MonoBehaviour {
    private Rigidbody rb;
    public WheelCollider[] wheels;
    public float motorForce = 3000;
    public float brakeTorque = 3000;

    void FixedUpdate() {
        float accel = Input.GetAxis("Vertical") * motorForce;
        float brake = Input.GetKey(KeyCode.Space) ? brakeTorque : 0;

        foreach (WheelCollider wheel in wheels) {
            wheel.motorTorque = accel;
            wheel.brakeTorque = brake;
        }
    }
}

Example 3: Ragdoll

// Enable/Disable ragdoll
void EnableRagdoll() {
    // Disable animator
    animator.enabled = false;

    // Enable all Rigidbodies
    Rigidbody[] allBodies = GetComponentsInChildren<Rigidbody>();
    foreach (Rigidbody body in allBodies) {
        body.isKinematic = false;
    }

    // The skeleton now simulates physics
}

Example 4: Projectile with Physics

// Realistic bullet/arrow
public class Projectile : MonoBehaviour {
    private Rigidbody rb;

    public void Launch(Vector3 direction, float force) {
        rb = GetComponent<Rigidbody>();
        rb.velocity = direction * force;

        // Rotate according to movement direction
        transform.rotation = Quaternion.LookRotation(direction);
    }

    void OnTriggerEnter(Collider collision) {
        if (collision.CompareTag("Enemy")) {
            Destroy(gameObject);
        }
    }
}

📚 Tabla de Referencia Rápida

Component/Method Description Performance
Rigidbody Controls physics of an object ⭐⭐⭐
Box Collider Cubic collider ⭐⭐⭐⭐⭐
Sphere Collider Spherical collider ⭐⭐⭐⭐⭐
Capsule Collider Cylindrical collider ⭐⭐⭐⭐⭐
Mesh Collider Exact geometry collider ⭐⭐ (Avoid if possible)
Physics.Raycast Detects collisions with a ray ⭐⭐⭐⭐
AddForce Applies cumulative force ⭐⭐⭐⭐⭐
Velocity Sets direct velocity ⭐⭐⭐⭐⭐
FixedJoint Fixes two bodies together ⭐⭐⭐
SpringJoint Creates elasticity ⭐⭐
HingeJoint Rotation articulation ⭐⭐⭐
CharacterJoint Complex articulation ⭐⭐

✅ Best Practices

✅ DO

  • Use primitive Colliders
  • Apply forces in FixedUpdate()
  • Use Raycasts for detection
  • Limit dynamic objects
  • Use Constraints to optimize
  • Profile performance regularly
  • Document physics values

❌ AVOID

  • Mesh Colliders on dynamic objects
  • Changing transform directly
  • Applying forces in Update()
  • Too many complex joints
  • Continuous Collision for everything
  • Ignoring the collision matrix
  • Physics without purpose

🔧 Troubleshooting

Q: My object falls through the floor

A: Common issues:

  • The floor has NO Collider
  • The Rigidbody has "Is Kinematic" enabled
  • The object's velocity is too high (use Continuous Collision)
  • The Collider is too small (check "Edit Collider" in Inspector)
Q: My character doesn't move smoothly

A: Solutions:

  • Apply forces in FixedUpdate(), not Update()
  • Use MovePosition() for smooth movement
  • Check Fixed Timestep (Project Settings > Time)
  • Make sure the Capsule Collider has the correct height
Q: Objects vibrate or behave erratically

A: This is "jitter":

  • Increase Solver Iterations in Physics Settings
  • Reduce Force Scale and Penetration per Iteration
  • Make sure Colliders don't overlap
  • Check that mass is realistic (not too small)
Q: Joint breaks or strange behaviour

A: Joint issues:

  • Verify that both Rigidbodies exist and are configured
  • Make sure the Connected Body is not null
  • Increase Solver Iterations if unstable
  • For ragdolls: configure Character Joints correctly

🎓 Conclusion

Unity's physics system is powerful but requires understanding. Remember:

  • Rigidbody + Collider = Base system (neither works without the other)
  • FixedUpdate() = The only correct way to apply forces
  • Primitives = Faster than Mesh Colliders
  • Physics Materials = Full control of behaviour
  • Joints = Create complex behaviours
  • Optimization = Essential for production games

The key is understanding the difference between what physics does automatically vs what needs to be controlled by code.

🚀 Next Steps:
  • Experiment with different values in Physics Settings
  • Create a small prototype: A ball rolling down a ramp
  • Build a simple ragdoll to understand Character Joints
  • Profile your game to identify physics bottlenecks

0 Comments

Post a Comment

Post a Comment (0)