Quick answer: Call skeleton_ik.start() to activate. Verify root_bone and tip_bone names match bones in the skeleton, target_node points to a valid Node3D, and interpolation is 1.0. Set a magnet for predictable elbow/knee direction.
Here is how to fix Godot SkeletonIK chain not following target. You add a SkeletonIK3D node, set root_bone to “UpperArm.L” and tip_bone to “Hand.L,” point target_node at a marker. The arm animation plays normally — no IK. You expected the hand to reach toward the marker. The SkeletonIK3D node is configured but not started.
The Symptom
SkeletonIK3D configured correctly (bones, target, interpolation) has no visible effect. Animation plays without IK override. Moving the target does not affect the bones.
What Causes This
start() not called. SkeletonIK3D is inactive until start() is explicitly called. Setting up the node in Inspector does not auto-start it. Unlike Animation Rigging in Unity which evaluates automatically, Godot requires manual activation.
Bone names mismatched. root_bone and tip_bone are strings. If the skeleton renamed a bone and you did not update the SkeletonIK3D, or capitalization differs, the IK silently does nothing.
Target node missing. target_node is a NodePath. If it points at a deleted or moved node, no IK. Verify the path resolves at runtime.
Interpolation at 0. interpolation = 0 means “IK has 0% influence.” The node runs but does not affect bones.
Magnet not set. Without use_magnet + magnet position, the IK solver picks an arbitrary pole. Bones may bend in odd directions though technically “toward target.”
The Fix
Step 1: Start the IK.
extends Node3D
@onready var ik: SkeletonIK3D = $Armature/Skeleton3D/SkeletonIK3D
func _ready():
ik.start()
func _on_weapon_pickup():
ik.interpolation = 1.0
func _on_weapon_drop():
ik.interpolation = 0.0
Call start() once to enable the IK. Modulate interpolation to blend IK in/out during gameplay without stopping the node.
Step 2: Verify bone names. Select the Skeleton3D. In the inspector you see the bone hierarchy. Note exact names. In SkeletonIK3D, root_bone and tip_bone must match exactly.
func _ready():
var skel = ik.get_parent() as Skeleton3D
if skel.find_bone(ik.root_bone) == -1:
push_error("Bone not found: " + ik.root_bone)
if skel.find_bone(ik.tip_bone) == -1:
push_error("Bone not found: " + ik.tip_bone)
Fails loudly if a bone name is wrong — fail-fast is better than silent no-op.
Step 3: Assign a target_node. In the inspector, target_node should be a NodePath to a Node3D that the tip bone will reach toward. A Marker3D or empty Node3D works. Move it at runtime to drive the IK.
func _physics_process(delta):
# Example: hand reaches toward closest enemy
var target = find_nearest_enemy()
if target:
$IKTargetMarker.global_position = target.global_position
Step 4: Set magnet for natural bend. Enable use_magnet. Set magnet position to where the elbow or knee should point. For a front-facing arm, offset the magnet backward (toward the character’s back); for a leg, offset forward.
ik.use_magnet = true
ik.magnet = Vector3(-0.5, 0, -0.3) # in local space of ik parent
Without magnet, the solver sometimes flips the elbow inside out (backward joint). Magnet avoids this.
Min/Max Iterations
For heavier IK solvers, adjust min_distance and max_iterations. max_iterations higher = more accurate but slower. For most use cases the defaults work; only tune if the IK visibly under-reaches.
“SkeletonIK is inactive by default. Call start(). Validate bone names at runtime. Magnet for predictability.”
Related Issues
For shader-related skeleton issues, see Godot Shader Uniform Not Updating. For animation player issues, AnimationPlayer Not Playing on Ready.
start() + correct bone names + target NodePath + magnet. Four ingredients for working IK.