AppleyAppley Docs
Docs/Physics

Rigidbodies

Master rigid body dynamics with forces, impulses, and constraints.

22 min read Intermediate Updated 2026-07-01 v2.0 ~75 min to complete

Introduction

Rigidbodies simulate realistic physics for dynamic objects. This guide covers forces, impulses, torque, constraints, and collision response.

Guide 11 of 25

This is part of the Intermediate Guides collection. Category: Physics. Estimated completion: 75 minutes. Difficulty: Intermediate.

Screenshot

Rigidbodies
Rigidbodies

Step-by-Step Guide

1

Add a rigidbody

Select a dynamic object and add a Rigidbody. Set mass, drag, and angular drag.

2

Apply forces

Use applyForce() for continuous forces (thrusters) and applyImpulse() for instant forces (explosions, jumps).

3

Apply torque

Use applyTorque() for rotational forces. Set angular drag to prevent infinite spinning.

4

Set constraints

Freeze specific axes: freeze X rotation to prevent falling over, freeze Z for 2D-style movement.

5

Configure collision detection

Use Discrete for slow objects, Continuous for fast ones (bullets, cars). Continuous prevents tunneling.

6

Use interpolation

Enable interpolation for smooth visual movement. Physics at 50Hz, rendering interpolates to 60FPS.

FluxScript Example

Here is a complete FluxScript implementation for this guide:

Rigidbodies — FluxScript
on start {
  ball = scene.find("PhysicsBall")
  ball.setRigidbody(true)
  ball.setMass(2.0)
  ball.setDrag(0.1)
  ball.setAngularDrag(0.5)
  ball.setCollider("sphere", { radius: 0.5 })
  ball.setBounce(0.7)
  ball.setInterpolation(true)
  ball.freezePosition(false, false, true)
}

on update(dt) {
  ball = scene.find("PhysicsBall")
  if input("space") ball.applyForce(vec3(0, 20, 0))
  if input("w") ball.applyForce(vec3(0, 0, 10))
  if input("a") ball.applyForce(vec3(-10, 0, 0))
}

on collision(other) {
  ball = scene.find("PhysicsBall")
  if other.type == "bumper" {
    dir = math.normalize(ball.position - other.position)
    ball.applyImpulse(dir * 15)
    ball.applyTorque(vec3(0, 5, 0))
    audio.play("bounce")
  }
}

on event("explosion", data) {
  bodies = physics.getRigidbodiesInRange(data.pos, 10)
  for i = 0 to bodies.length {
    dir = bodies[i].position - data.pos
    dist = math.length(dir)
    force = (1 - dist / 10) * 50
    bodies[i].applyImpulse(math.normalize(dir) * force)
  }
}

Node Graph Example

Prefer visual programming? Here is the equivalent Node Graph:

Rigidbodies — Node Graph
[On Start] --> [Set Rigidbody: mass=2, drag=0.1, bounce=0.7]
   --> [Freeze: Z position for 2D]

[On Update] --> [Input: space/w/a] --> [Apply Force]

[On Collision] --> [Branch: "bumper"]
   --> [Calculate: bounce direction]
   --> [Apply Impulse + Torque] --> [Play Audio]

[On Event "explosion"] --> [Get Rigidbodies in Range]
   --> [For Each: Apply Impulse with falloff]

Optimization Tips

Keep your implementation fast and efficient with these optimization tips:

  • Use Continuous collision detection only for fast-moving objects. It is 3-5x more expensive than Discrete.
  • Keep mass ratios reasonable (under 100:1). A 1000kg object hitting a 1kg object causes physics instability.
  • Use interpolation on all visible rigidbodies. Physics at 50Hz, rendering at 60FPS — interpolation smooths the gap.
  • Apply forces in on update, not on collision. Collision callbacks should set flags or apply impulses.

Common Mistakes

Tunneling through walls

Fast objects pass through thin colliders. Use Continuous detection or thicker colliders.

Objects spinning forever

Set angular drag > 0 (0.1-0.5). Without it, objects spin indefinitely.