Skip to content
Development
Skill

/physics-tuning

Tune game physics for stable, good-feeling motion — fixed vs variable timestep, render interpolation, mass/gravity/drag, continuous collision detection (CCD) to stop tunneling, fixing jitter, and collision layers/masks. Engine-neutral. Use when the user mentions physics feel,

From plugin
awesome-gamedev-agent-skills
45567 skills
Install
$ npx -y skills add gamedev-skills/awesome-gamedev-agent-skills --skill physics-tuning --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/physics-tuning

Context preview

The summary Claude sees to decide when to auto-load this skill.

Tune game physics for stable, good-feeling motion — fixed vs variable timestep, render interpolation, mass/gravity/drag, continuous collision detection (CCD) to stop tunneling, fixing jitter, and collision layers/masks. Engine-neutral. Use when the user mentions physics feel,

SKILL.md

physics-tuning.SKILL.md
name: physics-tuning
description: >
  Tune game physics for stable, good-feeling motion — fixed vs variable
  timestep, render interpolation, mass/gravity/drag, continuous collision
  detection (CCD) to stop tunneling, fixing jitter, and collision layers/masks.
  Engine-neutral. Use when the user mentions physics feel, jitter, tunneling,
  fixed timestep, FixedUpdate, CCD, bouncing/unstable physics, or collision layers.

Physics tuning

Most "bad physics" is not a bug in the engine — it's a mismatch between the **fixed-timestep simulation** and the **variable-rate render loop**, or untuned mass/drag/CCD/layer settings. This skill covers the engine-neutral knobs that make physics stable and responsive; pair it with `godot-physics` or `unity-physics` for the concrete APIs.

When to use

  • Use when motion jitters, objects pass through walls (tunneling), stacks

explode, or movement feels floaty/sticky/laggy.

  • Use to decide what goes in the fixed (physics) step vs the render frame, and

how to interpolate between them.

  • Use to tune gravity, mass, drag, restitution, solver iterations, sleeping, and

collision layers/masks.

**When *not* to use:** for an engine's exact physics nodes/components and collision callbacks, use `godot-physics` or `unity-physics`. For *movement decisions* (when to jump, AI steering) use `input-systems` and `game-ai`. For platformer jump-feel specifics like coyote time/jump buffering, that's input/ controller territory — see `input-systems` and the `platformer` genre.

Core workflow

1. **Run physics on a fixed timestep.** Simulate at a constant rate (e.g. 50–60 Hz). A fixed `dt` makes the simulation deterministic-ish and stable; a variable `dt` makes integration and collisions inconsistent. 2. **Put physics work in the physics callback**, not the render frame. Apply forces/velocities and read collisions in the fixed step (`FixedUpdate` / `_physics_process`), using that step's `dt`. 3. **Interpolate rendering between physics ticks.** The render frame rate ≠ the physics rate, so smoothly interpolate transforms toward the latest physics state, or enable the engine's Rigidbody interpolation, to remove visible stutter. 4. **Tune the body, not the scene.** Set mass for relative weight, drag for damping, gravity scale per object, and restitution/friction via materials. 5. **Stop tunneling with CCD** on small/fast bodies; cap maximum velocity. 6. **Stabilize stacks/joints** with more solver iterations, sane mass ratios, and sleeping for resting bodies. 7. **Verify by feel and stress test.** Play at low and high frame rates; throw fast objects at thin walls; stack and shove bodies. Report what you observed.

Patterns

1. Fixed timestep for simulation, render interpolation for smoothness

# Physics callback: runs at the FIXED rate. Use its dt for all integration.
func _physics_process(dt):                  # Unity: void FixedUpdate()
    velocity += gravity * dt                # integrate with the FIXED dt
    move_and_slide()                        # engine resolves collisions this step
    _prev_pos = _curr_pos; _curr_pos = global_position   # record for interpolation

# Render frame: runs as fast as the display. Interpolate between physics states.
func _process(_frame_dt):                   # Unity: void Update()
    var alpha = Engine.get_physics_interpolation_fraction()  # 0..1 within the tick
    visual.global_position = _prev_pos.lerp(_curr_pos, alpha)
# RIGHT: integrate in the fixed step, render via interpolation.
# WRONG: applying forces in _process/Update with frame dt — speed and collisions
# then depend on frame rate and jitter under load.

Most engines offer this for you (Godot `physics_interpolation`/Rigidbody interpolate; Unity `Rigidbody.interpolation = Interpolate`). Prefer the built-in before hand-rolling.

2. Stop tunneling: CCD + a speed cap

# Fast, small bodies skip past thin colliders between ticks. Two fixes:
body.continuous_cd = true            # RigidBody3D bool (RigidBody2D: CCD_MODE_* enum). Unity: rb.collisionDetectionMode = Continuous
# Cap velocity so a single step can't move more than ~one collider thickness.
const MAX_SPEED := 40.0
if velocity.length() > MAX_SPEED:
    velocity = velocity.normalized() * MAX_SPEED
# Rule of thumb: max_distance_per_step (= speed / physics_hz) should be < the
# thinnest wall. Raise physics_hz or enable CCD when that fails.

3. Body tuning: mass, drag, gravity scale, material

# Mass is RELATIVE weight in collisions; it does NOT change fall speed (gravity
# accelerates all masses equally). Use drag and gravity_scale to shape feel.
body.mass = 2.0                      # heavier pushes lighter in collisions
body.linear_damp = 0.5               # air drag: higher = stops sooner (Unity: drag)
body.gravity_scale = 1.5             # per-object gravity multiplier (snappier fall)
# Bounce/slide come from the physics material, not code:
material.bounce = 0.2                # restitution 0..1 (Unity: bounciness)
material.friction = 0.8              # surface grip

4. Collision layers and masks (who collides with whom)

# A body is ON its layer(s) and SCANS the layers in its mask. Both directions of a
# pair must be configured for them to interact.
player.collision_layer = LAYER_PLAYER
player.collision_mask  = LAYER_WORLD | LAYER_ENEMY     # player detects world+enemies
pickup.collision_layer = LAYER_PICKUP
pickup.collision_mask  = LAYER_PLAYER                  # pickup only reacts to player
# Unity equivalent: assign GameObject layers and edit the Physics collision matrix
# (or Physics.IgnoreLayerCollision). Keep a named layer constant table, not magic numbers.

Pitfalls

  • **Applying forces/movement in the render frame** (`Update`/`_process`) makes

behavior frame-rate dependent — faster PCs run faster, and collisions get flaky. Do simulation in the fixed step.

  • **Visible jitter** even
Read more
Ships withawesome-gamedev-agent-skills

<img src="docs/assets/banner.png" width="820" alt="awesome-gamedev-agent-skills — game-dev skills for AI coding agents.

Get the whole plugin
Stats
458
Stars
36
Forks
Active
Maintenance
Python
Language
Apache-2.0
License
1d ago
Last commit
1mo ago
Created

Repo: gamedev-skills/awesome-gamedev-agent-skills