iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Physics

Game physics simulates motion, collisions, forces. Most engines bundle a physics library (Unity: PhysX, Godot: GodotPhysics / Jolt, Unreal: Chaos). The pieces you wire up: rigid bodies, colliders, gravity, joints, raycasts.

Rigid bodies, collisions, raycasts (Unity)

EXAMPLE
using UnityEngine;

// 1) Make something physical — add Rigidbody + Collider
// Inspector: add Rigidbody (mass, drag, gravity) + a Collider (Box, Sphere, Capsule, Mesh)

public class Ball : MonoBehaviour
{
    Rigidbody rb;
    [SerializeField] float jumpForce = 8f;

    void Awake() => rb = GetComponent<Rigidbody>();

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

// 2) Continuous vs discrete collision detection
// rb.collisionDetectionMode = CollisionDetectionMode.Continuous;  // for fast-moving objects (bullets)
// Discrete = cheaper, occasional tunneling. Continuous = no tunneling, costlier.

// 3) Use FixedUpdate for physics — runs at the physics tick (default 50 Hz)
void FixedUpdate()
{
    rb.MovePosition(rb.position + transform.forward * speed * Time.fixedDeltaTime);
}

// 4) Forces vs velocities
rb.AddForce(Vector3.right * 10);              // affected by mass + drag
rb.AddForce(Vector3.up * 10, ForceMode.Impulse);  // instant velocity change
rb.velocity = Vector3.zero;                    // hard reset
rb.AddTorque(Vector3.up * 5);                  // rotational force

// 5) Collision callbacks
void OnCollisionEnter(Collision c)
{
    if (c.gameObject.CompareTag("Enemy"))
        TakeDamage();
    var impact = c.relativeVelocity.magnitude;
    audio.PlayOneShot(thudSound, Mathf.Clamp01(impact / 10f));
}

void OnCollisionStay(Collision c) { /* still touching */ }
void OnCollisionExit(Collision c) { /* separated */ }

// 6) Triggers — detect overlap WITHOUT physical response
void OnTriggerEnter(Collider c)
{
    if (c.CompareTag("Pickup"))
    {
        Destroy(c.gameObject);
        score += 10;
    }
}
// Trigger requires: collider.isTrigger = true on at least one of the colliders

// 7) Layers + Layer Collision Matrix
// Edit → Project Settings → Physics → Layer Collision Matrix
// Lets you say "Player layer doesn't collide with Pickup layer" — big perf win

// 8) Raycast — line of sight, picking, ground check
bool grounded;
void CheckGrounded()
{
    grounded = Physics.Raycast(transform.position, Vector3.down, out var hit, 1.1f);
    if (grounded) Debug.DrawLine(transform.position, hit.point, Color.green);
}

RaycastHit hit;
if (Physics.Raycast(camera.position, camera.forward, out hit, 100f, enemyLayer))
{
    hit.collider.GetComponent<Enemy>().Hit();
}

// 9) OverlapSphere / Box — find everything in a radius
Collider[] inRange = Physics.OverlapSphere(transform.position, 5f, enemyLayer);
foreach (var c in inRange) c.GetComponent<Enemy>().Aggro();

// 10) Joints — connect rigid bodies
var hinge = gameObject.AddComponent<HingeJoint>();
hinge.connectedBody = otherRigidbody;
hinge.anchor = new Vector3(0, 0.5f, 0);
hinge.axis   = Vector3.up;

// 11) Kinematic — physics object you move manually
rb.isKinematic = true;             // gravity off, no forces; you control position/rotation
// Useful for moving platforms, animated objects that need to collide

// 12) Common pitfalls
// - Moving with transform.position bypasses physics — use rb.MovePosition
// - Calling AddForce in Update can be frame-rate dependent — use FixedUpdate or pass Time.fixedDeltaTime
// - Tiny / huge masses break the solver — keep within 0.1..100 range
// - High velocity + Discrete CCD = tunneling through walls — switch to Continuous
// - Using mesh colliders on moving objects — convex MeshCollider with isConvex=true

// 13) Physics in Godot (similar pattern)
// extends RigidBody3D
// func _physics_process(delta):
//     if Input.is_action_just_pressed("jump"):
//         apply_central_impulse(Vector3.UP * 8)
// func _on_body_entered(body): pass

// 14) When to skip physics
// - Static obstacles: just use colliders, no Rigidbody
// - UI / 2D widget interactions: events, not physics
// - Custom motion (platformer-style precise control) — implement your own character controller with raycasts
//   (Unity has CharacterController and ThirdPersonController templates)

Why it matters

Use Rigidbody.MovePosition + FixedUpdate for physics motion; use raycasts for ground checks and aiming. Mixing transform.position writes and physics solving is the source of 80% of janky game feel.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Use a real physics engine for non-trivial games:
//   2D: Matter.js (web), Box2D, Chipmunk
//   3D: Rapier, Cannon-es, PhysX (Unity), Jolt (Godot 4)
// Roll your own only for highly stylised, simple games.
Try it Yourself »

Discussion

Loading…