IKControl: making the character's hand reach an object without animating the arm
Inverse kinematics lets you pose several bones by moving one. IKControl brings that outside the animation editor, at run time — and it has four properties that have to be right.
Produced with AI from the sources cited below, and checked by automated verification against those same sources. No person read this text before publication. Editorial Policy

Making a character put their hand on a door handle looks like an animation problem, and it is — until the handle changes height. Then the animation that fitted one door does not fit the other, and the solution becomes one animation per door.
Inverse kinematics solves that by flipping the question. Instead of "what angles do the bones need", it answers "where does the hand need to be" — and works out the angles by itself.
The problem
The official definition is short: inverse kinematics is a common animation technique for making characters move and interact with the environment realistically.
The reason it exists is written down too, and it is honest about the work it replaces: creating realistic movement by hand usually requires many iterations and fine adjustments to several joints. Anyone who has tried posing an arm bone by bone — shoulder, elbow, wrist, and back to the shoulder because the result came out crooked — recognises the description.
The promise is the inversion: with IK, you can pose and animate several parts of the character by adjusting a single object.
The documentation gives three examples, and they cover the space of uses well:
- Posing the hand while the linked limbs adjust automatically — wrist, elbow and shoulder.
- Making the feet interact realistically with different surfaces and slopes.
- Moving a single target object to quickly create realistic interactions with characters and props.
The second is the one that most changes the perception of quality in a game, and the one fewest people implement: a character standing on a ramp with both feet at the same height is one of the things that makes a game look stiff, and almost nobody can name what is wrong.
Step by step
IKControl adds IK to rigs procedurally, outside the animation editor. That is the central point: it works at run time, reacting to the world, not in a recorded animation.
The documentation warns before listing: the mandatory properties have to be right to avoid unexpected and unnatural results. There are four.
Type specifies the control's behaviour type. The common types are Position and Transform. The practical difference: Position makes the effector chase the target's position; Transform chases position and orientation. A hand holding a lever needs to be in the right position and rotated correctly — that is Transform. A hand pointing at a spot is Position.
EndEffector is the rig's BasePart or Bone that chases the target. In the official example, the left hand bone as the effector, to reach a door handle.
Target is the object the effector reaches or points at. And the definition is generous: it can be any object with a world position — a part, an attachment, whatever is there.
ChainRoot defines the chain of parts or bones the control affects. Every part connected between the ChainRoot and the EndEffector is affected.
That last one is what gives fine control over the result, and the documentation's example explains it better than any description: putting the ChainRoot on the left upper arm makes the IK apply to the whole left arm; putting it on the left forearm makes it apply only from the elbow down.
It is a choice of style, not of correctness. A long chain reaches further and moves the shoulder, which can fight the animation that is playing. A short chain preserves the shoulder's pose and reaches less.
The rule of thumb that works: start with the shortest chain that solves the case, and only lengthen it if the reach falls short. Every extra bone in the chain is one more bone the IK can pose in a way you did not anticipate — and it is always the shoulder, always in one specific animation, always after the game is already live.
There is also a consequence that only appears with the rig in motion. A chain that includes the shoulder competes with the torso animation: a character who walks and reaches at the same time has the shoulder pulled from both sides, and the result is a sway that comes from nowhere. A short chain does not have that problem because the shoulder still belongs to the animation.
To test, the documentation suggests a route that needs no script at all: you can add and edit IKControl from a script or directly in the Explorer — and you can even add and change it during a playtest. Start the test, find your character model in the Workspace (it is named after your Roblox account), add an Attachment to the root, position it in front, and create the IKControl on the Humanoid pointing at it.
The artifact
The script below creates the IKControl at run time and makes the right hand reach the nearest tagged object, letting go when it moves away.
Two of its decisions are worth explaining. The first: the control is born switched off. With no target there is nothing to reach, and IK switched on with no target produces an arbitrary pose.
The second is the one that separates IK that looks good from IK that looks like a defect: the weight ramps up gradually. Switching the control on at once makes the arm jump to position, in the same frame. It is the most artificial effect IK can produce, and it is the first thing you notice in a game.
Common mistakes
The visually loudest mistake is the elbow bending the wrong way.
That happens because, mathematically, there is more than one way for the hand to reach the requested point — and nothing in the computation knows that human elbows only bend one way. The result is an arm that reaches the target perfectly and looks broken.
The official solution is constraints: they exist to limit how the joints move while reaching the target, and that is what ensures elbows and knees bend naturally.
But here is the detail that makes people give up: a constraint and IK only talk to each other if three conditions are met, and one of them is geometric and unforgiving.
The first is about parentage — the constraint and the IKControl have to share the same parent model.
The second is about the attachments the constraint references: they have to be on the same parts as the corresponding Motor6D's Part0 and Part1.
The third is the demanding one: the relative positions of the constraint's attachments have to be equal to the corresponding positions in the Motor6D's C0 and C1 CFrames. Not "similar" — equal. An attachment positioned by eye, dragged with the mouse until it looks right, almost certainly does not satisfy that. And the symptom of not satisfying it is not an error: it is a joint that behaves inexplicably.
The way to get it right is computing the position from the Motor6D, instead of positioning by hand. It is the kind of thing solved by a setup script run once over the rig, and never solved by dragging attachments in the viewport.
That is worth spelling out because it is the point at which most people abandon constraints: they are not hard to understand, they are hard to position. Anyone who tries by eye concludes constraints do not work, and goes back to living with the inverted elbow.
The second common mistake is IK fighting the animation. The control moves the same bones as the animation that is playing, and when the two disagree the result is a shaking limb. The way out is the weight: instead of on or off, a transition, and a weight below the maximum when you want partial influence on top of the animation.
The third is expecting IK to reach the unreachable. If the target is further away than the arm, the chain stretches to its limit and stays there, rigid. Checking the distance before switching on — as the artifact does — avoids the stretched-puppet pose.
Next step
The use with the biggest visual return is not the hand: it is the feet. A character standing on a ramp with both feet at the same height, or floating a centimetre above the step, is a defect the player feels without being able to name.
The recipe is the same as for the arm, with a raycast per foot to find the ground height and a target positioned there. The short chain is usually enough, and a weight proportional to how still the character is stops the effect fighting the walk animation.
After that, it is worth investing in constraints. They are laborious because of the position requirements, and they are what separates a character who reaches things from a character who looks like they reach things. The documentation describes the process with a hinge constraint at the elbow and a ball socket at the wrist, which is the pair that solves most arms.
Sources
Ready-to-use artifact
-- ServerScriptService: makes the character's hand reach the nearest object
-- tagged as reachable, and let go when it moves away.
--
-- The four mandatory properties, and what each one decides:
-- Type -> HOW to reach (Position follows position only;
-- Transform follows position AND orientation)
-- EndEffector-> WHO reaches (the hand)
-- Target -> WHAT to reach (any object with a world position)
-- ChainRoot -> HOW FAR the chain goes (the shoulder = whole arm;
-- the forearm = elbow down only)
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local CollectionService = game:GetService("CollectionService")
local DISTANCE = 6 -- studs: how far the arm tries to reach
local TAG = "Reachable"
local function nearestTarget(root)
local best, bestDist = nil, DISTANCE
for _, object in CollectionService:GetTagged(TAG) do
local position = object:IsA("BasePart") and object.Position
or (object:IsA("Attachment") and object.WorldPosition)
if position then
local d = (position - root.Position).Magnitude
if d < bestDist then
best, bestDist = object, d
end
end
end
return best
end
local function prepareArm(character)
local humanoid = character:WaitForChild("Humanoid")
local root = character:WaitForChild("HumanoidRootPart")
local hand = character:WaitForChild("RightHand", 10)
local shoulder = character:WaitForChild("RightUpperArm", 10)
if not hand or not shoulder then
-- a rig without those parts: probably not R15
warn("rig without RightHand/RightUpperArm: IK not applied")
return
end
-- The IKControl lives in the Humanoid (or in the AnimationController).
local ik = Instance.new("IKControl")
ik.Name = "ReachWithRight"
ik.Type = Enum.IKControlType.Position
ik.EndEffector = hand
ik.ChainRoot = shoulder
ik.Enabled = false -- born off: with no target, there is nothing to reach
ik.Parent = humanoid
local connection
connection = RunService.Heartbeat:Connect(function()
if not character.Parent or humanoid.Health <= 0 then
connection:Disconnect()
ik:Destroy()
return
end
local target = nearestTarget(root)
if target then
ik.Target = target
-- Weight ramps up: switching on at once makes the arm JUMP
-- to position, which is the most artificial effect IK can
-- produce.
ik.Enabled = true
ik.Weight = math.min(ik.Weight + 0.08, 1)
else
ik.Weight = math.max(ik.Weight - 0.08, 0)
if ik.Weight <= 0 then
ik.Enabled = false
end
end
end)
end
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(prepareArm)
end)


