How to smooth out a bone's orientation from client to server?

My game uses skinned mesh rigs for each character, and for each player I want their character’s head to look up and down based on the camera’s CFrame. Because bone orientation doesn’t replicate, I am forced to use a remoteevent in order to replicate the orientation for all players to see, with the cost of being heavy on performance.

This is all fine and good, all I had to do was make it not fire every frame so it wouldn’t melt people’s devices. However, this obviously made the movements choppy, and I would like to be able to smooth them out without decreasing performance due to remote spam.

LocalScript

local player = game:GetService("Players").LocalPlayer
local cam = workspace.CurrentCamera

local camPosOld = 0
local event = script:WaitForChild("RemoteEvent")

while task.wait(.1) do
	camPosValue = Vector3.new(0,0,0 - (cam.CFrame:ToOrientation() * 40))
	if camPosValue ~= camPosOld then --No point firing if the camera is still
		event:FireServer(camPosValue)
	end
	camPosOld = camPosValue
end

Server script

local event = script.Parent:WaitForChild("RemoteEvent")
local bone = script.Parent.Parent:WaitForChild("HumanoidRootPart").Bip001['Bip001 Pelvis']['Bip001 Spine']['Bip001 Spine1']['Bip001 Spine2']

local db = false

event.OnServerEvent:Connect(function(player,pos)
	if not db then db = true
		bone.Orientation = pos
		task.wait(.1)
		db = false
	end
end)

I have tried using both tweens and math.lerp–tweens I tried long ago and I don’t recall exactly why they didn’t work, and math.lerp didn’t work probably because I don’t understand how it works. I tried applying it to the part where it sets the bone’s orientation to ‘pos’ but it just resulted in the bone not updating at all.

Any help would be greatly appreciated! :]

Bumping this in hopes someone will be able to help :pray: :pray:

I’d recommend using something like RenderStepped instead of task.wait() because then it actually fires every frame. Also the debounce will affect the smoothness of the movement because it is limiting it to 10 frames per second. You can also try out just using cam:GetPropertyChangedSignal(“CFrame”):Connect(function()) to see if that works better for you. Good Luck!

Yeah the debounce is there on purpose to make sure nobody can spam the remote event faster than it should be fired. Thanks for the PropertyChangedSignal tip though, didn’t think of that

You can use game:GetService(“RunService”).Heartbeat:Wait() as a debounce which should limit it. However I don’t really think it is possible to spam any faster than that, so the debounce is useless.

Edit: Also I’ve never really experienced any lag from using runservice to fire remotes so yea.