CFraming overcorrecting and choppy...?

I have the following code in a server script, attempting to aim the player’s arm and head at the mouse location.

-- Create arm motor6d
		local shoulder = plr.Character.Torso:FindFirstChild("Right Shoulder")
		local baseC0 = shoulder.C0
		local aimMotor = shoulder:Clone()
		aimMotor.Name = "Aim Motor"
		aimMotor.Parent = plr.Character.Torso
		
		-- Create head motor6d
		local neck = plr.Character.Torso:FindFirstChild("Neck")
		local neckBaseC0 = neck.C0
		local neckAimMotor = neck:Clone()
		neckAimMotor.Name = "Neck Aim Motor"
		neckAimMotor.Parent = plr.Character.Torso
		
		
		-- Set up aim connection
		aimConnection = runServ.Stepped:Connect(function()
			
			local mousePos = game.ReplicatedStorage.MiscRemoteEvents.getMouse:InvokeClient(plr)
			mousePos = plr.Character.Torso.CFrame:PointToObjectSpace(mousePos)
			
			-- Aim arm
			local offset = CFrame.lookAt(Vector3.new(0, 0, 0), mousePos)
			local aimCFrame = baseC0:ToObjectSpace(offset) * CFrame.Angles(0, math.rad(90), math.rad(90))
			--aimMotor.C0 = baseC0 * aimCFrame.Rotation * CFrame.new(0, -.5, -.5) -- Can't use transform on the server because Heartbeat, so this its analog
			game:GetService("TweenService"):Create(aimMotor, TweenInfo.new(.1), {C0 = baseC0 * aimCFrame.Rotation * CFrame.new(0, -.5, -.5)}):Play()
			
			-- Aim head
			local neckAimCFrame = neckBaseC0:ToObjectSpace(offset * CFrame.Angles(math.rad(90), math.rad(180), 0))
			neckAimMotor.C0 = neckBaseC0 * neckAimCFrame.Rotation
		
		end)

It works well:


Maybe a taaaaad bit choppy (if you know why that’s happening, do share, but I don’t think it’s too noticeable).
The problem comes when I do the other part, which is aiming the player’s body as well:

-- Start aiming
		aimConnection = runServ.Stepped:Connect(function()
			
			-- Aim player
			local aim = game.Players.LocalPlayer:GetMouse().Hit.Position

			local root = game.Players.LocalPlayer.Character.HumanoidRootPart
			root.CFrame = CFrame.lookAt(root.Position, Vector3.new(aim.X, root.Position.Y, aim.Z))-- * CFrame.Angles(0, math.rad(90), 0)

		end)


It works, but as you can see,

  • The head and arm aim way past the target, and then fall back into place
  • The head and arm are very choppy when you walk

If I had to guess, it’s something with how the head tries to position first, then the client does the torso and replicates to the server, and then the server adjusts accordingly, causing the overcorrection and the choppiness.
If my guess is correct, then

  • How do I fix it?
  • Can I instead do the body rotation on the server somehow? My current method doesn’t work; you can’t even move
  • Is there a secret third thing I could do?
1 Like

If I understand correctly, then the problem is indeed most likely due to once the torso rotates, the already rotated arm and head rotate even more, causing them to overshoot. Perhaps you could just… change the order?

Also, you should basically never do these kinds of things on the server. The amount of server → client → server invokes every second is just too much. Mostly if you get more players. IIRC the limit for RemoteEvents is 15 times per second. I’d assume it wouldn’t be much better for RemoteFunctions. The client should automatically replicate the movements if done properly, so you shouldn’t need to do that on the server. The choppyness is also most likely cause from the delay between the server and the client.

I don’t really know how I’d do that, since the order seems to be up to delay between the server and the client, unless I misunderstand.

Well, then how will I get the rotation to replicate? It works with setting the CFrame of the HumanoidRootPart on the client, that replicates, but the Motor6D stuff hasn’t, unless I’ve done something wrong. This seems to be the most likely thing, so do tell how I can correct it, if you know.

I’m not doing it with remote events. I’m using an attribute, and whenever that attribute is changed to true the server picks up on it and connects the RunService.Stepped function. It disconnects it when the attribute is changed back to false.