Quick answer: Set freeze = true with freeze_mode = FREEZE_MODE_KINEMATIC on pickup, then parent under the holder. On drop, unparent and unfreeze. Avoid force-based hold which accumulates angular velocity.
Here is how to fix Godot 4 picked-up RigidBody3D objects that spin uncontrollably while held. Force-based hold (apply force toward target) is unstable; freeze+kinematic provides clean control.
The Symptom
Player picks up a box. While carrying, the box spins faster and faster, eventually flinging itself away. Or held box behaves erratically when bumped against geometry.
What Causes This
Force-based hold instability. Continuous force toward target compounds with collision impulses; angular velocity accumulates without bound.
No angular damping. Angular damp = 0 means no resistance to rotation; small impulses build up.
Holding while still simulating. Physics keeps applying gravity, contacts; held object fights them all.
The Fix
Step 1: Use freeze + kinematic on pickup.
extends CharacterBody3D
var held: RigidBody3D
func pickup(body: RigidBody3D):
held = body
held.freeze = true
held.freeze_mode = RigidBody3D.FREEZE_MODE_KINEMATIC
held.reparent($Camera/HoldPosition)
held.position = Vector3.ZERO
func drop():
if held == null: return
var world_pos = held.global_position
held.reparent(get_tree().root)
held.global_position = world_pos
held.freeze = false
held = null
Reparenting to the camera makes the body follow head movement exactly without spinning.
Step 2: Add angular damping for fallback.
body.angular_damp = 5.0 # strong resistance to rotation
Even when not held, this prevents accumulated spin from light collisions.
Step 3: Lock rotation axes if needed.
body.lock_rotation = true # no rotation at all
# or per-axis
body.axis_lock_angular_x = true
body.axis_lock_angular_y = false
body.axis_lock_angular_z = true
Step 4: For physical hold (Half-Life style), use a constraint. A PinJoint3D between the held body and a hand bone provides physics-correct hold without manual freeze. More complex setup but more interactive.
Step 5: Verify drop preserves position. When dropping, capture global_position before reparenting; reapply after to avoid sudden teleports.
“Freeze + kinematic + reparent. Three steps for stable hold without spin.”
Related Issues
For RigidBody2D sleep, see RigidBody2D Sleep. For 3D character stairs, see 3D Stair Stepping.
freeze + kinematic on pickup. Reparent to hand. Unfreeze on drop. Held objects stay still.