Prevent IKControl from snapping

Hey! My game uses IKControl to move arms to the cursor position, but sometimes arms snap to positions, making the game very hard. Any fix to this?


Relevant code snippets:

local function createIKControl(humanoid, chainRootName, endEffectorName, priority)
	local char = humanoid.Parent
	local ik = Instance.new("IKControl")
	ik.Type = Enum.IKControlType.Position
	ik.ChainRoot = char:FindFirstChild(chainRootName)
	ik.EndEffector = char:FindFirstChild(endEffectorName)

	-- Create a part to hold the attachment target
	local targetPart = Instance.new("Part")
	targetPart.Name = chainRootName .. "_IKTarget"
	targetPart.Size = Vector3.new(0.1, 0.1, 0.1)
	targetPart.Transparency = 1
	targetPart.Anchored = true
	targetPart.CanCollide = false
	targetPart.CanQuery = false
	targetPart.CanTouch = false
	targetPart.Parent = workspace

	-- Create and parent the attachment properly
	local att = Instance.new("Attachment")
	att.Name = chainRootName .. "_Target"
	att.Parent = targetPart

	ik.Target = att
	ik.Weight = 10
	ik.Priority = priority or 1 -- (Priority is always 10)
	ik.SmoothTime = 0.1
	ik.Enabled = false
	ik.Parent = humanoid

	return ik, targetPart
end

local function setupIK()
	local char = player.Character
	if not char then return end
	local humanoid = char:FindFirstChildOfClass("Humanoid")
	if not humanoid or humanoid.RigType ~= Enum.HumanoidRigType.R15 then return end

	leftIK, leftIKTargetPart = createIKControl(humanoid, "LeftUpperArm", "LeftHand", 10)
	rightIK, rightIKTargetPart = createIKControl(humanoid, "RightUpperArm", "RightHand", 10)
end

local function clampReach(pos, armLength)
	local root = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
	if not root then return pos end

	local direction = (pos - root.Position)
	if direction.Magnitude > armLength then
		direction = direction.Unit * armLength
	end
	return root.Position + direction
end

local function getMousePositionOnPlane()
	local character = player.Character
	if not character then return Vector3.zero end
	local root = character:FindFirstChild("HumanoidRootPart")
	if not root then return Vector3.zero end
	local pos = mouse.Hit.Position
	return Vector3.new(pos.X, pos.Y, root.Position.Z)
end

RunService.RenderStepped:Connect(function()
	local targetPos = getMousePositionOnPlane()

	if leftIK and leftIKTargetPart then
		if holdingM1 then
			leftIK.Enabled = true
			leftIKTargetPart.Position = clampReach(targetPos, maxArmReach)
		else
			leftIK.Enabled = false
		end
	end

	if rightIK and rightIKTargetPart then
		if holdingM2 then
			rightIK.Enabled = true
			rightIKTargetPart.Position = clampReach(targetPos, maxArmReach)
		else
			rightIK.Enabled = false
		end
	end
end)
1 Like

I can see a couple of lines that change the Enabled property of the IK control in your code, which I’ve found to cause IK controls to snap. If you want it to stop applying its effects, you should set its Weight property to 0 instead. Try replacing all ik.Enabled = false lines to ik.Weight = 0 and all ik.Enabled = true lines to ik.Weight = 1.

1 Like

i thought this would work, but it still happens and the arms go back to their default position when the IK weight is zero. i also tried lerping the position, didn’t change much because it’s in a loop obviously

From the clip you just provided, it looks like the IK controls are doing what they’re programmed to do. They only look like they’re snapping because they’re trying to perform a large rotation over the span of a millisecond. I’d probably just increase the SmoothTime property to 0.5 or something.

That said, I assume you’ve set the SmoothTime property to 0.1 for a reason and that increasing it is not an option. If that’s the case, you might have to get creative with preventing the IK control from trying to rotate too far. The first solution that came to mind was to set the Type property to LookAt and have the hooks (assuming they’re the End Effector) aim away from the player’s body by messing around with the Offset property. You might want to then set a Pole to prevent the arm from bending upwards. Alternatively, you could set the Type to Transform and try to get your Target to do the rotating for you. This does end up changing how the hooks would work a bit, so if maintaining the current behavior is important for you, this solution might not work out so well.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.