Server-Side Torso Movements Not Rotating Correctly

I have a script that rotates the player’s torso and head toward the direction of their mouse, and this works perfectly fine, other than the fact that it is on the client-side rather than server.

Client Script:

local RunService = game:GetService("RunService")

local Player = game.Players.LocalPlayer
local PlayerMouse = Player:GetMouse()

local Camera = workspace.CurrentCamera

local Character = Player.Character or Player.CharacterAdded:Wait()
local Head = Character:WaitForChild("Head")
local Neck = Head:WaitForChild("Neck")

local Torso = Character:WaitForChild("UpperTorso")
local Waist = Torso:WaitForChild("Waist")

local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")

local NeckOriginC0 = Neck.C0
local WaistOriginC0 = Waist.C0

Neck.MaxVelocity = .01

RunService.RenderStepped:Connect(function() 
	local CameraCFrame = Camera.CoordinateFrame

	if Character:FindFirstChild("UpperTorso") and Character:FindFirstChild("Head") then
		local TorsoLookVector = Torso.CFrame.lookVector
		local HeadPosition = Head.CFrame.p

		if Neck and Waist then
			if Camera.CameraSubject:IsDescendantOf(Character) or Camera.CameraSubject:IsDescendantOf(Player) then
				local Point = PlayerMouse.Hit.p

				local Distance = (Head.CFrame.p - Point).magnitude
				local Difference = Head.CFrame.Y - Point.Y

				Neck.C0 = Neck.C0:lerp(NeckOriginC0 * CFrame.Angles(-(math.atan(Difference / Distance) * 0.5), (((HeadPosition - Point).Unit):Cross(TorsoLookVector)).Y * 1, 0), 0.5 / 2)
				Waist.C0 = Waist.C0:lerp(WaistOriginC0 * CFrame.Angles(-(math.atan(Difference / Distance) * .8), (((HeadPosition - Point).Unit):Cross(TorsoLookVector)).Y * 0.5, 0), 0.5 / 2)
			end
		end
	end	
end)

Client FPV View:


Client Freecam View:

In order to convert the client script into a server script I split it into 2 different scripts, a local script that sends client data, and a server script that actually modifies the player’s torso and head, the required info for rotation is sent through a remote event with the name “UpdateNeckAndWaist.”

But once ran, the script seems to constantly be applying the rotation to the player’s torso and head whenever they move their mouse.

I have tried rewriting it probably 5 times now and I just have no clue what I’m doing wrong.

New Local Script:

local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Player = game.Players.LocalPlayer
local PlayerMouse = Player:GetMouse()

local Camera = workspace.CurrentCamera

local RemoteEvent = ReplicatedStorage:WaitForChild("UpdateNeckAndWaist")



RunService.RenderStepped:Connect(function()
	local Point = PlayerMouse.Hit.p
	local CameraCFrame = Camera.CFrame
	local CamSub = Camera.CameraSubject

	RemoteEvent:FireServer(Point, CameraCFrame, CamSub) 
end)

New Server Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local RemoteEvent = ReplicatedStorage:WaitForChild("UpdateNeckAndWaist")

RemoteEvent.OnServerEvent:Connect(function(Player, Point, CameraCFrame, CamSub)
	local Character = Player.Character
	if not Character then return end
	
	local Head = Character:WaitForChild("Head")
	local Neck = Head:WaitForChild("Neck")

	local Torso = Character:WaitForChild("UpperTorso")
	local Waist = Torso:WaitForChild("Waist")
	
	local NeckOriginC0 = Neck.C0
	local WaistOriginC0 = Waist.C0
	
	Neck.MaxVelocity = .01

	if Character:FindFirstChild("UpperTorso") and Character:FindFirstChild("Head") then
		local TorsoLookVector = Torso.CFrame.lookVector
		local HeadPosition = Head.CFrame.p

		if Neck and Waist then
			if CamSub:IsDescendantOf(Character) or CamSub:IsDescendantOf(Player) then

				local Distance = (Head.CFrame.p - Point).magnitude
				local Difference = Head.CFrame.Y - Point.Y

				Neck.C0 = Neck.C0:lerp(NeckOriginC0 * CFrame.Angles(-(math.atan(Difference / Distance) * 0.5), (((HeadPosition - Point).Unit):Cross(TorsoLookVector)).Y * 1, 0), 0.5 / 2)
				Waist.C0 = Waist.C0:lerp(WaistOriginC0 * CFrame.Angles(-(math.atan(Difference / Distance) * .8), (((HeadPosition - Point).Unit):Cross(TorsoLookVector)).Y * 0.5, 0), 0.5 / 2)
			end
		end
	end	
end)

New FPV View:


New Freecam View:

(It also looks the same on other player’s/the server’s camera)

If any confusion was caused by my use of freecam, server-side, and client-side, I have a script that basically just unlocks the camera so I can see from any angle on client mode

1 Like

(Basically my third-person camera wasn’t on server mode)