Optimizing character head aim with animations (avoiding RemoteEvents)

I’m trying to make my character aim their head toward the mouse using animation weights instead of manually rotating Motor6Ds. Firing a RemoteEvent 30 times a second per aiming player (to update Motor6D angles) seems taxing on the server. Roblox’s animation system replicates automatically, seems more efficient, and works well in theory. The issue is some visual jank when you go from tilting up to down, and how slow your head takes to tilt once you toggle it.

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")

local player = Players.LocalPlayer
local mouse = player:GetMouse()

local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local rootPart = character:WaitForChild("HumanoidRootPart")
local head = character:WaitForChild("Head")

local Up = script:WaitForChild("Up")
local Down = script:WaitForChild("Down")
local TiltUp = humanoid:LoadAnimation(Up)
local TiltDown = humanoid:LoadAnimation(Down)

local lookConnection = nil

local function startLookAt()
	lookConnection = RunService.RenderStepped:Connect(function()
		local mousePos = mouse.Hit.Position
		local rootPos = rootPart.Position
		local headPos = head.Position

		-- Setting Up Animations for tilting head and limbs
		TiltUp:Play()
		TiltDown:Play()
		TiltUp:AdjustWeight(0)
		TiltDown:AdjustWeight(0)

		-- Face the Root horizontally toward the mouse (Y rotation)
		local horizontalLook = CFrame.new(rootPos, Vector3.new(mousePos.X, rootPos.Y, mousePos.Z))
		local _, yaw, _ = horizontalLook:ToEulerAnglesYXZ()
		rootPart.CFrame = CFrame.new(rootPos) * CFrame.Angles(0, yaw, 0)

		-- Adjust neck pitch (X rotation only)
		local direction = (mousePos - headPos).Unit
		local pitch = math.asin(direction.Y)  -- vertical angle only
		local clampedPitch = math.clamp(pitch, math.rad(-50), math.rad(50))
		local PitchDeg = math.deg(clampedPitch)

		if PitchDeg > 0 then
			TiltDown:AdjustWeight(0)
			TiltUp:AdjustWeight(PitchDeg/100)
		elseif PitchDeg < 0 then
			TiltUp:AdjustWeight(0)
			TiltDown:AdjustWeight(math.abs(PitchDeg/100))
		end
		--neck.C0 = originalNeckC0 * CFrame.Angles(-clampedPitch, 0, 0)
	end)
end

local function stopLookAt()
	if lookConnection then
		TiltUp:Stop()
		TiltDown:Stop()
		lookConnection:Disconnect()
		lookConnection = nil
	end

	--if neck and originalNeckC0 then
		--neck.C0 = originalNeckC0 -- Reset neck position
	--end
end

local function InputBegan(input,gpe)
	if gpe then return end

	if input.KeyCode == Enum.KeyCode.F then
		if lookConnection then
			stopLookAt()
		else
			startLookAt()
		end
	end
end

-- Toggle on F key press
UserInputService.InputBegan:Connect(InputBegan)

It may be worth to lerp the animation weights, but I’d need to continuously update the weight values.