Godot 4.6 makes Jolt the default 3D physics: do old projects switch?
Godot 4.6 sets Jolt Physics for new 3D projects; existing ones stay on GodotPhysics3D. The behaviour differences, the settings that matter, and how to migrate and test.
- Godot 4.6 (26 Jan 2026) writes physics/3d/physics_engine = Jolt Physics into new projects; existing projects are untouched
- DEFAULT currently means GodotPhysics3D, but the docs say that may change, so pin the engine explicitly in shipped projects
- Jolt differs in single-body joints, collision margins, depenetration, ray-cast face index and the size of WorldBoundaryShape3D
- Migrate on a branch, run every physics scene, and compare results with numbers, not by eye
Godot 4.6 shipped on 26 January 2026 with one big change for 3D games: Jolt Physics is the default physics engine for new 3D projects, replacing GodotPhysics3D. The common misunderstanding is that old projects move over automatically. They do not. This article explains the actual mechanism, the behaviour that differs, and a migration you can measure.
Facts checked against the Godot 4.6 release page, the stable Using Jolt Physics docs, ProjectSettings.xml at tag 4.6-stable, and PR #105737, which made Jolt the default, as of October 2026. (4.7 is out now, but this change started in 4.6.)
What changed and what did not
PR #105737 shows Godot did not change the setting’s default value. Instead, the project manager writes this into project.godot when you create a new project:
[physics]
3d/physics_engine="Jolt Physics"
The default of physics/3d/physics_engine is still DEFAULT, and the 4.6 ProjectSettings reference says DEFAULT is currently equivalent to GodotPhysics3D but may change in future releases; select an explicit engine if you want your project to stay put.
| Situation | In project.godot | Engine you get in 4.6 |
|---|---|---|
| New project created in 4.6+ | "Jolt Physics" | Jolt |
| Old project, never touched this setting | no line → DEFAULT | GodotPhysics3D (may change later) |
| Old project with GodotPhysics3D selected | "GodotPhysics3D" | GodotPhysics3D |
touch project.godot, then open the editor | the editor fills in "Jolt Physics" | Jolt |
If you have a shipped 3D game that is not migrating yet, set
GodotPhysics3Dexplicitly today so a future upgrade does not quietly swap engines under you.
How Jolt behaves differently
The Using Jolt Physics page lists the differences. The ones that bite real games most often:
- Single-body joints. With a body on only one side of a joint, the other side counts as “the world”. Jolt and GodotPhysics3D disagree on which side that is, which inverts the joint’s limits. Fix with
physics/jolt_physics_3d/joints/world_node, or move the body to the other slot - Unsupported joint properties such as
bias,softnessandrelaxationon HingeJoint3D, and soft limits on Generic6DOFJoint3D. Non-default values emit a warning - Collision margins. Jolt uses a “convex radius”: it shrinks the shape, then adds the margin back as a shell, so the size does not grow but corners round off (GodotPhysics3D ignores margin entirely)
- Overlapping bodies. GodotPhysics3D pushes them apart like a spring and can overshoot; Jolt corrects position only, so it never overshoots but can take longer
- Ray-cast
face_indexis always-1until you enablequeries/enable_ray_cast_face_index - Kinematic-frozen RigidBody3D reports no contacts with static or kinematic bodies until you enable
simulation/generate_all_kinematic_contacts - Area3D and SoftBody3D. Jolt emits
body_enteredfor soft bodies; GodotPhysics3D does not - WorldBoundaryShape3D is no longer unbounded
Worked example: three defaults that change your game quietly
1. A WorldBoundaryShape3D floor that ends
physics/jolt_physics_3d/limits/world_boundary_shape_size defaults to 2000.0: the plane sits in the middle of a 2000 m box.
- Half of 2000 = 1000
- Anything more than 1000 m from the centre along the plane does not collide with it An open-world or endless-runner game using a plane as the ground will see the player fall through once they go far enough.
2. Rounded box corners
collision_margin_fraction defaults to 0.08, times the shape’s shortest axis, capped by Shape3D.margin (default 0.04).
- A 2 × 0.5 × 1 m box → 0.08 × 0.5 = 0.04 m → within the cap → 4 cm
- A 0.2 × 0.2 × 0.2 m box → 0.08 × 0.2 = 1.6 cm A 4 cm round on a person-sized crate is invisible, but stacking boxes precisely or rolling a ball off a table edge will show it.
3. How slowly overlaps resolve (a simplified model counting only Baumgarte)
baumgarte_stabilization_factor defaults to 0.2: fix 20% of the penetration each step.
- A 10 cm overlap leaves 10 × 0.8ⁿ cm after n steps
- Below 1 cm needs 0.8ⁿ < 0.1 → n > ln 0.1 ÷ ln 0.8 ≈ 10.3 → 11 steps
- At
physics_ticks_per_second= 60 → 11 × 16.7 ms ≈ 183 ms A character spawned inside a wall slides out over about a fifth of a second instead of being launched.
Migrating an existing project, step by step
- Branch in git first. Switching engines is one line, so it is easy to undo
- Project Settings > Physics > 3D > Physics Engine →
Jolt Physics, then Save & Restart - Read the Output panel for warnings about unsupported joint properties and fix them
- Check every single-body joint for inverted limits
- Search your code for
face_index,get_contact_impulse(), and Area3D with soft bodies, and decide which settings to enable - Run every scene with physics. 4.6 adds game speed controls in the editor; slow things down to watch collisions
- Measure. A tiny test scene that drops a body and logs its position over time, run under both engines:
# test_drop.gd — attach to a RigidBody3D, run under both engines, compare
extends RigidBody3D
var _ticks := 0
func _physics_process(_delta: float) -> void:
_ticks += 1
var hz := Engine.physics_ticks_per_second
if _ticks % (hz / 2) == 0: # print every half second; count ticks, don't sum floats
print("%.2f s y=%.3f vy=%.3f" % [float(_ticks) / hz, global_position.y, linear_velocity.y])
if _ticks >= hz * 3:
get_tree().quit()
If your game depends heavily on physics timing, read fixed timestep game loops alongside this: _physics_process runs on a fixed 60 ticks a second by default, whichever engine you use.
Common mistakes
- Assuming upgrading to 4.6 gives you Jolt. Old projects stay on DEFAULT = GodotPhysics3D
- Leaving it on DEFAULT. The day DEFAULT changes, your game changes engine without anyone deciding to. Pin it
- Setting collision margin fraction to 0 for sharp edges. The docs warn values near 0 reduce accuracy for convex shapes
- Computing damage from
get_contact_impulse(). In Jolt it is estimated ahead of time and only accurate when the two bodies touch nothing else - Moving from the Godot Jolt extension with old setting names. The category moved from
physics/jolt_3dtophysics/jolt_physics_3d, and several values changed from percent to fraction - Turning on Run On Separate Thread. The docs call it lightly tested; treat it as experimental
Sources
FAQ
If I open a 4.5 project in 4.6, do I get Jolt automatically?
No. The 4.6 release notes say existing projects are not affected. Only projects created in 4.6 or later get the Jolt line written into project.godot.
Does 2D physics change too?
No. This is 3D only; the setting is physics/3d/physics_engine. 2D has its own separate setting.
Can I keep using the Godot Jolt extension?
Yes, but the docs say it is in maintenance mode; the module built into Godot since 4.4 is the main one. Settings moved from physics/jolt_3d to physics/jolt_physics_3d, and the extension's Jolt-specific joint nodes are not in the built-in module.
Commands and settings were tested on sample systems. Try them on a test machine before production.