Character's arm position error [Inverse Kinematics]

Hey guys! I hope you are doing very very well! Being direct, I’m trying to make a complete arm movement but I Got a problem, when I replicate the movement, the arm movement to the player next to you is bugged and you see his arm into another position than the actual one:

Player 1 Screen:

image

Player 2 Screen:

image

Basically, there’s a cube on the workspace that is going to be cloned for every player on the game, so player1 has the “Target1” Cube, and player2 has the “Target2” Cube, etc.

This is because the arm is pointing to this cube. And when you move your mouse your “special” cube moves to the mouse position.

The problem is that as you can see the limbs bug for every player, and I don’t really know the why of this, I really really really appreciate your help if you can give me a hand with this, even if it’s the smallest one, and I also thank you for giving me your time reading this (and maybe trying to help me)

If you need more information don’t think of it, and write it down in the comments!

Here’s the script that moves your arm (with Inverse Kinematics):

(It’s a LocalScript)

local player = game.Players.LocalPlayer

	--Cloning the players "special" cubes--

		--The default cube that is going to be clonned is "Target"

		local player1 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player1
		local player2 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player2
		local player3 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player3
		local player4 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player4
		local player5 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player5
		local player6 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player6
		local player7 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player7
		local player8 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player8
		local player9 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player9
		local player10 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player10
		local player11 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player11
		local player12 = game.ReplicatedStorage:WaitForChild('PlayerPointTOCUBES').Player12

		wait(25)

		if player.Name == player1.Value then
			local Cube1 = game.Workspace.Target:Clone()
			Cube1.Parent = game.Workspace
			Cube1.Name = "Target1"
			
		elseif player.Name == player2.Value then
			local Cube2 = game.Workspace.Target:Clone()
			Cube2.Parent = game.Workspace
			Cube2.Name = "Target2"
			
		elseif player.Name == player3.Value then
			local Cube3 = game.Workspace.Target:Clone()
			Cube3.Parent = game.Workspace
			Cube3.Name = "Target3"
			
		elseif player.Name == player4.Value then
			local Cube4 = game.Workspace.Target:Clone()
			Cube4.Parent = game.Workspace	
			Cube4.Name = "Target4"
			
		elseif player.Name == player5.Value then	
			local Cube5 = game.Workspace.Target:Clone()
			Cube5.Parent = game.Workspace	
			Cube5.Name = "Target5"
			
		elseif player.Name == player6.Value then	
			local Cube6 = game.Workspace.Target:Clone()
			Cube6.Parent = game.Workspace	
			Cube6.Name = "Target6"
			
		elseif player.Name == player7.Value then	
			local Cube7 = game.Workspace.Target:Clone()
			Cube7.Parent = game.Workspace	
			Cube7.Name = "Target7"
			
		elseif player.Name == player8.Value then	
			local Cube8 = game.Workspace.Target:Clone()
			Cube8.Parent = game.Workspace	
			Cube8.Name = "Target8"
			
		elseif player.Name == player9.Value then	
			local Cube9 = game.Workspace.Target:Clone()
			Cube9.Parent = game.Workspace	
			Cube9.Name = "Target9"
			
		elseif player.Name == player10.Value then
			local Cube10 = game.Workspace.Target:Clone()
			Cube10.Parent = game.Workspace
			Cube10.Name = "Target10"
			
		elseif player.Name == player11.Value then	
			local Cube11 = game.Workspace.Target:Clone()
			Cube11.Parent = game.Workspace	
			Cube11.Name = "Target11"
			
		elseif player.Name == player12.Value then
			local Cube12 = game.Workspace.Target:Clone()
			Cube12.Parent = game.Workspace	
			Cube12.Name = "Target12"
			
		end	

	--Cloning the players "special" cubes--

local pi				=math.pi
local halfpi			=pi/2
local forwardV3			=Vector3.new(0,0,-1) -- Constant

--[[ 
	
		OriginCFrame is the CF of the shoulder joint, this can be gotten using some CFrame:
		upperTorso.CFrame * shoulderJoint.C0
		Note that the shoulderJoint.C0 would be the INITIAL shoulderJoint C0, before anything has been done
		
		targetPos is the target Position you are trying to point to, this will be a Vector3 in the world space
		
		a is the length of the upper arm, I use 0.515
		
		b is the length of the lower arm + the hand, I use 1.1031
--]]

local function solveArm(originCFrame,targetPosition,a,b)
	-- Localize the targetPosition in regards to originCFrame
	local localized = originCFrame:pointToObjectSpace(targetPosition)
	local localizedUnit = localized.unit

	-- Construct a CFrame pointing from the shoulder position to the target position
	local axis = forwardV3:Cross(localizedUnit)
	local angle = math.acos(-localizedUnit.Z)
	local plane = originCFrame*CFrame.fromAxisAngle(axis,angle)

	-- Get the length from the origin to our target position
	local c = localized.Magnitude

	-- If c is between the lengths of a and b then return an offsetted plane so that one of the lengths reaches the goal,
	-- but the other length is folded so it looks natural
	if c < math.max(a,b)-math.min(a,b) then
		return plane * CFrame.new(0,0,math.max(b,a)-math.min(b-a)-c), -halfpi, pi

		-- If c > a + b then return flat angles and an offsetted plane which reaches its target
	elseif c > a+b then
		return plane * CFrame.new(0,0,a+b-c), halfpi, 0

		-- Otherwise, use the law of cosines
	else
		local theta1 = -math.acos((-(b * b) + (a * a) + (c * c)) / (2 * a * c)) -- law of cosines, gets the angle opposite b
		local theta2 = math.acos(((b  * b) - (a * a) + (c * c)) / (2 * b * c)) -- law of cosines, gets the angle opposite a
		return plane, theta1 + halfpi, theta2 - theta1
	end
end

wait(5)

-- Demonstration for how this can be called:

	--Giving the cubes--
local Target = nil

if player.Name == player1.Value then
	local targetObj	= workspace:WaitForChild("Target1")
	Target = "Target1"
	
elseif player.Name == player2.Value then
	local targetObj	= workspace:WaitForChild("Target2")
	Target = "Target2"
	
elseif player.Name == player3.Value then
	local targetObj	= workspace:WaitForChild("Target3")
	Target = "Target3"
	
elseif player.Name == player4.Value then
	local targetObj	= workspace:WaitForChild("Target4")
	Target = "Target4"
	
elseif player.Name == player5.Value then	
	local targetObj	= workspace:WaitForChild("Target5")
	Target = "Target5"
	
elseif player.Name == player6.Value then	
	local targetObj	= workspace:WaitForChild("Target6")
	Target = "Target6"
	
elseif player.Name == player7.Value then	
	local targetObj	= workspace:WaitForChild("Target7")
	Target = "Target7"
	
elseif player.Name == player8.Value then	
	local targetObj	= workspace:WaitForChild("Target8")
	Target = "Target8"
	
elseif player.Name == player9.Value then	
	local targetObj	= workspace:WaitForChild("Target9")
	Target = "Target9"
	
elseif player.Name == player10.Value then
	local targetObj	= workspace:WaitForChild("Target10")
	Target = "Target10"
	
elseif player.Name == player11.Value then	
	local targetObj	= workspace:WaitForChild("Target11")
	Target = "Target11"
	
elseif player.Name == player12.Value then
	local targetObj	= workspace:WaitForChild("Target12")
	Target = "Target12"
end


	--Giving the cubes--

local character			= player.Character
local upperTorso		=character:WaitForChild("UpperTorso")
local rightUpperArm		=character:WaitForChild("RightUpperArm")
local rightLowerArm		=character:WaitForChild("RightLowerArm")
local rightShoulder		=rightUpperArm:WaitForChild("RightShoulder")
local rightElbow		=rightLowerArm:WaitForChild("RightElbow")
local rightShoulderInit	=rightShoulder.C0	-- This can be a preset value, since it will always be the same, it is the offset from the UpperTorso to the RightShoulder joint
local rightElbowInit	=rightElbow.C0		-- This can be a preset value, since it will always be the same, it is the offset from the RightUpperArm to the RightElbow joint

local tp0				=CFrame.new((upperTorso.CFrame * CFrame.new(1.25,0,-1)).p)*CFrame.Angles(0,math.pi/2,0)

------------------Make everyone see your arm's position---

local tweenService = game:GetService("TweenService")

game.ReplicatedStorage.LookArm.OnClientEvent:Connect(function(otherPlayer, rightShoulderCFRAME, rightElbowCFRAME)

	local RightShoulder = otherPlayer.Character.RightUpperArm:FindFirstChild("RightShoulder")
	local RightElbow = otherPlayer.Character.RightLowerArm:FindFirstChild("RightElbow")

	if RightShoulder then
		tweenService:Create(RightShoulder, TweenInfo.new(.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out, 0, false, 0), {C0 = rightElbowCFRAME}):Play()
	end

	if RightElbow then
		tweenService:Create(RightElbow, TweenInfo.new(.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out, 0, false, 0), {C0 = rightElbowCFRAME}):Play()
	end

end)

-------------------Make everyone see your arm's position---


while wait() do
	
	local targetObj	= workspace:WaitForChild(Target)
	local targetPos		= targetObj.Position
	local shoulderCF	=upperTorso.CFrame * rightShoulderInit
	local plane, shoulderAngle, elbowAngle	= solveArm(shoulderCF, targetPos, 0.515, 1.031)
	-- (Just ignore this because this was the old code) rightShoulder.C0 	=upperTorso.CFrame:toObjectSpace(plane) * CFrame.Angles(shoulderAngle, 0, 0)
	-- (Just ignore this because this was the old code) rightElbow.C0		=rightElbowInit * CFrame.Angles(elbowAngle, 0, 0)

	local goalRightShoulderC0CFrame = upperTorso.CFrame:toObjectSpace(plane) * CFrame.Angles(shoulderAngle, 0, 0)
	rightShoulder.C0 	=goalRightShoulderC0CFrame.Rotation + rightShoulder.C0.Position
	rightElbow.C0		=rightElbowInit * CFrame.Angles(elbowAngle, 0, 0)

	game.ReplicatedStorage.PointToArm:FireServer(player, rightShoulder.C0, rightElbow.C0)


end

Thank you for your help and have a nice day! bye bye! :grinning_face_with_smiling_eyes: :wink: :wave:
Don’t mind to ask for more information, just write what you need on the comments and I’ll be answering you! :wink: :grinning_face_with_smiling_eyes: :wave: