Help with Motor6D arm animation

I have a script that attempts to aim the player’s arm at the mouse cursor. It seems as if it is working… but only sometimes.

-- Create arm motor6d
		local shoulder = plr.Character.Torso:FindFirstChild("Right Shoulder")
		local baseC0 = shoulder.C0
		local aimMotor = shoulder:Clone()
		aimMotor.C0 *= CFrame.Angles(0, -math.pi/2, math.pi/2)
		aimMotor.Name = "AimMotor"
		aimMotor.Parent = plr.Character.Torso
		
		-- Set up aim connection
		aimConnection = runServ.Heartbeat:Connect(function()
			
			local mousePos = game.ReplicatedStorage.MiscRemoteEvents.getMouse:InvokeClient(plr)
			
			-- Aim arm
			aimMotor.C0 = baseC0 * CFrame.new(Vector3.new(0, 0, 0), mousePos)
			aimMotor.C0 = aimMotor.C0:ToWorldSpace(CFrame.Angles(0, -math.rad(90), math.rad(90)))
			
		end)

Note: This is in a server script, as I want the animation to replicate to the server, and doing this in a local script didn’t replicate.

Here’s what happens:


Some observations:

  • I can’t aim down
  • Aiming up starts aiming down for some reason
  • Even the horizontal movement, that kinda works, seems just generally off

I should note that this has an animation to go with it that aims the player sideways, with a blank keyframe for the arm to overwrite roblox’s idle animations; using it without the animation, it looks like this:


It seems to work better at spawn near the origin, so maybe it’s some issue with position vs CFrame somewhere? I don’t know.

Hi! I hope i’m not too late. Here’s your script:

-- Create arm motor6d
local shoulder = plr.Character.Torso:FindFirstChild("Right Shoulder")
local baseC0 = shoulder.C0
local aimMotor = shoulder:Clone()
aimMotor.C0 *= CFrame.Angles(0, -math.pi/2, math.pi/2)
aimMotor.Name = "AimMotor"
aimMotor.Parent = plr.Character.Torso

-- Set up aim connection
aimConnection = runServ.Heartbeat:Connect(function()

	local mousePos = game.ReplicatedStorage.MiscRemoteEvents.getMouse:InvokeClient(plr)

	local MotorWorldSpace = plr.Character.Torso.CFrame+Vector3.new(1, 0.5, 0)
	local RelativeMousePos = MotorWorldSpace:ToObjectSpace(mousePos).Position

	-- Aim arm
	aimMotor.C0 = baseC0 * CFrame.lookAt(Vector3.new(0, 0, 0), RelativeMousePos)
	local X, Y, Z = aimMotor.C0.Rotation:ToOrientation()
	aimMotor.C0 = CFrame.new(aimMotor.C0.Position) * CFrame.Angles(X, Y, math.rad(90))

end)

Your mistake was that you used mouse position in world space, so lookAt gave you incorrect vector.

local MotorWorldSpace = plr.Character.Torso.CFrame+Vector3.new(1, 0.5, 0)
This line transform Motor’s position from Torso object space to world space.

local RelativeMousePos = MotorWorldSpace:ToObjectSpace(mousePos).Position
This line make AimMotor be as origin (Basically)

aimMotor.C0 = baseC0 * CFrame.lookAt(Vector3.new(0, 0, 0), RelativeMousePos)
We can consider this Vector3.zero as our AimMotor position

local X, Y, Z = aimMotor.C0.Rotation:ToOrientation()
This give you rotation in radians

aimMotor.C0 = CFrame.new(aimMotor.C0.Position) * CFrame.Angles(X, Y, math.rad(90))
I don’t know how to explain this line, i found it just brute forcing possible combinations.

It also have some troubles with pointing up and down, but this much better than at start.