physics-tuning
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePhysics 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 or
for the concrete APIs.
godot-physicsunity-physics大多数「糟糕的物理效果」并非引擎bug——而是fixed-timestep模拟与可变帧率渲染循环不匹配,或是质量/阻力/CCD/层参数未调优导致的。本技能涵盖不绑定特定引擎的关键参数调节方法,可让物理系统更稳定、响应更流畅;若需具体API操作,请搭配或技能使用。
godot-physicsunity-physicsWhen 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 or . For movement
decisions (when to jump, AI steering) use and . For
platformer jump-feel specifics like coyote time/jump buffering, that's input/
controller territory — see and the genre.
godot-physicsunity-physicsinput-systemsgame-aiinput-systemsplatformer- 当运动出现抖动、物体穿墙(穿模)、堆叠物体爆炸,或移动手感飘/粘/延迟时使用。
- 用于确定哪些逻辑应放在固定(物理)时间步中,哪些放在渲染帧中,以及如何在两者之间进行插值。
- 用于调优重力、质量、阻力、弹性、求解器迭代次数、休眠状态以及碰撞层/遮罩。
不适用场景:若需了解引擎特定的物理节点/组件及碰撞回调,请使用或技能。若涉及移动决策(如何时跳跃、AI转向),请使用和技能。对于平台跳跃游戏中诸如 coyote time( coyote时间)/跳跃缓冲等特定手感细节,属于输入/控制器范畴——请参考技能及游戏类型相关内容。
godot-physicsunity-physicsinput-systemsgame-aiinput-systemsplatformerCore workflow
核心工作流程
- Run physics on a fixed timestep. Simulate at a constant rate (e.g. 50–60
Hz). A fixed makes the simulation deterministic-ish and stable; a variable
dtmakes integration and collisions inconsistent.dt - Put physics work in the physics callback, not the render frame. Apply
forces/velocities and read collisions in the fixed step (/
FixedUpdate), using that step's_physics_process.dt - 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.
- Tune the body, not the scene. Set mass for relative weight, drag for damping, gravity scale per object, and restitution/friction via materials.
- Stop tunneling with CCD on small/fast bodies; cap maximum velocity.
- Stabilize stacks/joints with more solver iterations, sane mass ratios, and sleeping for resting bodies.
- 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.
- 以固定时间步运行物理模拟。以恒定速率(如50–60 Hz)进行模拟。固定的(时间步长)可让模拟具备近似确定性且更稳定;可变
dt会导致积分计算和碰撞检测结果不一致。dt - 将物理逻辑放在物理回调中,而非渲染帧。在固定时间步(/
FixedUpdate)中施加力/速度并读取碰撞信息,使用该时间步的_physics_process进行计算。dt - 在物理 tick 之间插值渲染。渲染帧率≠物理模拟速率,因此需将变换平滑插值至最新物理状态,或启用引擎的刚体插值功能,以消除可见卡顿。
- 调优物体属性,而非场景属性。设置质量以体现相对重量,设置阻力以实现阻尼效果,为每个物体设置重力缩放比例,并通过材质设置弹性/摩擦力。
- 为小体积/高速物体启用CCD以防止穿模;同时限制最大速度。
- 通过增加求解器迭代次数、合理的质量比以及为静止物体启用休眠,稳定堆叠物体/关节。
- 通过手感测试和压力测试验证效果。在低帧率和高帧率下测试;用高速物体撞击薄墙;堆叠并推动物体。记录观察到的结果。
Patterns
实践模式
1. Fixed timestep for simulation, render interpolation for smoothness
1. 固定时间步模拟,渲染插值保证流畅性
gdscript
undefinedgdscript
undefinedPhysics callback: runs at the FIXED rate. Use its dt for all integration.
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
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.
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)
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.
RIGHT: integrate in the fixed step, render via interpolation.
WRONG: applying forces in _process/Update with frame dt — speed and collisions
WRONG: applying forces in _process/Update with frame dt — speed and collisions
then depend on frame rate and jitter under load.
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.
大多数引擎已内置此功能(Godot的`physics_interpolation`/刚体插值;Unity的`Rigidbody.interpolation = Interpolate`)。优先使用内置功能,而非手动实现。2. Stop tunneling: CCD + a speed cap
2. 防止穿模:CCD + 速度上限
gdscript
undefinedgdscript
undefinedFast, small bodies skip past thin colliders between ticks. Two fixes:
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
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.
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
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
Rule of thumb: max_distance_per_step (= speed / physics_hz) should be < the
thinnest wall. Raise physics_hz or enable CCD when that fails.
thinnest wall. Raise physics_hz or enable CCD when that fails.
undefinedundefined3. Body tuning: mass, drag, gravity scale, material
3. 物体调优:质量、阻力、重力缩放比例、材质
gdscript
undefinedgdscript
undefinedMass is RELATIVE weight in collisions; it does NOT change fall speed (gravity
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.
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)
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:
Bounce/slide come from the physics material, not code:
material.bounce = 0.2 # restitution 0..1 (Unity: bounciness)
material.friction = 0.8 # surface grip
undefinedmaterial.bounce = 0.2 # restitution 0..1 (Unity: bounciness)
material.friction = 0.8 # surface grip
undefined4. Collision layers and masks (who collides with whom)
4. 碰撞层与遮罩(谁与谁发生碰撞)
gdscript
undefinedgdscript
undefinedA body is ON its layer(s) and SCANS the layers in its mask. Both directions of a
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.
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
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
Unity equivalent: assign GameObject layers and edit the Physics collision matrix
(or Physics.IgnoreLayerCollision). Keep a named layer constant table, not magic numbers.
(or Physics.IgnoreLayerCollision). Keep a named layer constant table, not magic numbers.
undefinedundefinedPitfalls
常见陷阱
- Applying forces/movement in the render frame (/
Update) makes behavior frame-rate dependent — faster PCs run faster, and collisions get flaky. Do simulation in the fixed step._process - Visible jitter even with a fixed step usually means no render interpolation: the physics rate and display rate beat against each other. Enable interpolation.
- Tunneling through thin walls: discrete collision misses fast movers. Enable CCD, cap speed, thicken walls, or raise the physics rate.
- Expecting heavier objects to fall faster. Gravity is acceleration; mass
affects collision response, not fall speed. Use /drag for feel.
gravity_scale - Exploding stacks / jittery joints: mass ratios too extreme, or too few solver iterations. Keep mass ratios modest and raise iteration counts.
- Bodies that never rest burn CPU and twitch. Enable sleeping and a sensible sleep threshold for resting objects.
- One-directional layer setup: A's mask includes B but B's mask excludes A. Detection/collision can need both sides; verify the full matrix.
- Huge spikes (load hitches, breakpoints) blow up integration. Clamp the max physics step / substep count so a stall doesn't launch everything.
dt
- 在渲染帧(/
Update)中施加力/移动逻辑会导致行为依赖帧率——性能更好的电脑运行速度更快,碰撞检测也会变得不稳定。请在固定时间步中进行模拟。_process - 即使使用固定时间步仍出现可见抖动通常意味着未启用渲染插值:物理模拟速率与显示帧率不同步。请启用插值功能。
- 穿墙(穿模):离散碰撞检测会漏掉高速移动的物体。启用CCD、限制速度、加厚墙体,或提高物理模拟速率。
- 认为较重物体下落更快:重力是加速度;质量影响碰撞响应,而非下落速度。请使用/阻力来调整手感。
gravity_scale - 堆叠物体爆炸 / 关节抖动:质量比过于极端,或求解器迭代次数过少。请保持适度的质量比,并增加迭代次数。
- 物体永不休眠会占用CPU并出现抽搐。请为静止物体启用休眠功能,并设置合理的休眠阈值。
- 单向层设置:A的遮罩包含B,但B的遮罩排除A。碰撞检测/交互可能需要双向配置;请验证完整的碰撞矩阵。
- 巨大的峰值(加载卡顿、断点)会导致积分计算异常。请限制最大物理时间步/子步数,避免卡顿导致物体飞出去。
dt
References
参考资料
- — the fixed-timestep accumulator loop, interpolation math, substepping, CCD modes, solver/iteration tuning, sleeping, and a stability checklist.
references/timestep-and-ccd.md
- ——涵盖固定时间步累加循环、插值算法、子步模拟、CCD模式、求解器/迭代次数调优、休眠状态,以及稳定性检查清单。
references/timestep-and-ccd.md
Related skills
相关技能
- ,
godot-physics— concrete bodies, colliders, and callbacks.unity-physics - — responsive controls, jump buffering, coyote time.
input-systems - — agent movement that must agree with the physics step.
game-ai - ,
platformer— genres whose feel depends on this tuning.fps-shooter
- 、
godot-physics——具体的物体、碰撞器及回调操作。unity-physics - ——响应式控制、跳跃缓冲、coyote时间。
input-systems - ——需与物理时间步同步的AI移动逻辑。
game-ai - 、
platformer——手感依赖本调优技能的游戏类型。fps-shooter