Server Sided Character Tilting

I saw this video: Server Side Head/Camera Movement (R6/R15) - Roblox (Remote Events and Tweening)

I tried recreating it in Roblox for it to work with a character tilting system. Whenever I play it in a local server it doesn’t work and the other players look normal.

Screenshot 2024-06-24 223209

This is the local script

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

local LocalPlayer = Players.LocalPlayer

local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()

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

local RootJoint = HumanoidRootPart:WaitForChild("RootJoint")
local Neck = Torso:WaitForChild("Neck")
local RightShoulder = Torso:WaitForChild("Right Shoulder")
local LeftShoulder = Torso:WaitForChild("Left Shoulder")
local RightHip = Torso:WaitForChild("Right Hip")
local LeftHip = Torso:WaitForChild("Left Hip")

local RootJointC0 = RootJoint.C0
local NeckC0 = Neck.C0
local RightShoulderC0 = RightShoulder.C0
local LeftShoulderC0 = LeftShoulder.C0
local RightHipC0 = RightHip.C0
local LeftHipC0 = LeftHip.C0

local RootJointTilt = CFrame.new()
local NeckTilt = CFrame.new()
local RightShoulderTilt = CFrame.new()
local LeftShoulderTilt = CFrame.new()
local RightHipTilt = CFrame.new()
local LeftHipTilt = CFrame.new()

local DefaultLerpAlpha = 0.145 -- Lerping Speed
local dotThreshold = 0.9 -- dotThreshold (Do not edit)
local lastTime = 0 -- Last Time (Do not edit)
local tickRate = 1 / 60 -- 60 fps limit

local function UpdateDirectionalMovement(DeltaTime)
	local Now = workspace:GetServerTimeNow() -- os.clock Instead? Idrk

	if Now - lastTime >= tickRate then
		lastTime = Now

		local MoveDirection = HumanoidRootPart.CFrame:VectorToObjectSpace(Humanoid.MoveDirection)

		if MoveDirection:Dot(Vector3.new(1,0,-1).Unit) > dotThreshold then
			-- print("Forwards-Right")

			RootJointTilt = RootJointTilt:Lerp(CFrame.Angles(math.rad(-MoveDirection.Z) * 5, 0, math.rad(-MoveDirection.X) * 25), DefaultLerpAlpha)
			RootJoint.C0 = RootJointC0 * RootJointTilt



			RightShoulderTilt = RightShoulderTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			RightShoulder.C0 = RightShoulderC0 * RightShoulderTilt

			LeftShoulderTilt = LeftShoulderTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			LeftShoulder.C0 = LeftShoulderC0 * LeftShoulderTilt

			RightHipTilt = RightHipTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			RightHip.C0 = RightHipC0 * RightHipTilt

			LeftHipTilt = LeftHipTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			LeftHip.C0 = LeftHipC0 * LeftHipTilt
		elseif MoveDirection:Dot(Vector3.new(1,0,1).Unit) > dotThreshold then
			-- print("Backwards-Right")

			RootJointTilt = RootJointTilt:Lerp(CFrame.Angles(math.rad(-MoveDirection.Z) * 5, 0, math.rad(MoveDirection.X) * 25), DefaultLerpAlpha)
			RootJoint.C0 = RootJointC0 * RootJointTilt



			RightShoulderTilt = RightShoulderTilt:Lerp(CFrame.Angles(0, math.rad(MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			RightShoulder.C0 = RightShoulderC0 * RightShoulderTilt

			LeftShoulderTilt = LeftShoulderTilt:Lerp(CFrame.Angles(0, math.rad(MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			LeftShoulder.C0 = LeftShoulderC0 * LeftShoulderTilt

			RightHipTilt = RightHipTilt:Lerp(CFrame.Angles(0, math.rad(MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			RightHip.C0 = RightHipC0 * RightHipTilt

			LeftHipTilt = LeftHipTilt:Lerp(CFrame.Angles(0, math.rad(MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			LeftHip.C0 = LeftHipC0 * LeftHipTilt
		elseif MoveDirection:Dot(Vector3.new(-1,0,1).Unit) > dotThreshold then
			-- print("Backwards-Left")

			RootJointTilt = RootJointTilt:Lerp(CFrame.Angles(math.rad(-MoveDirection.Z) * 5, 0, math.rad(MoveDirection.X) * 25), DefaultLerpAlpha)
			RootJoint.C0 = RootJointC0 * RootJointTilt



			RightShoulderTilt = RightShoulderTilt:Lerp(CFrame.Angles(0, math.rad(MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			RightShoulder.C0 = RightShoulderC0 * RightShoulderTilt

			LeftShoulderTilt = LeftShoulderTilt:Lerp(CFrame.Angles(0, math.rad(MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			LeftShoulder.C0 = LeftShoulderC0 * LeftShoulderTilt

			RightHipTilt = RightHipTilt:Lerp(CFrame.Angles(0, math.rad(MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			RightHip.C0 = RightHipC0 * RightHipTilt

			LeftHipTilt = LeftHipTilt:Lerp(CFrame.Angles(0, math.rad(MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			LeftHip.C0 = LeftHipC0 * LeftHipTilt
		elseif MoveDirection:Dot(Vector3.new(-1,0,-1).Unit) > dotThreshold then
			-- print("Forwards-Left")

			RootJointTilt = RootJointTilt:Lerp(CFrame.Angles(math.rad(-MoveDirection.Z) * 5, 0, math.rad(-MoveDirection.X) * 25), DefaultLerpAlpha)
			RootJoint.C0 = RootJointC0 * RootJointTilt

	

			RightShoulderTilt = RightShoulderTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			RightShoulder.C0 = RightShoulderC0 * RightShoulderTilt

			LeftShoulderTilt = LeftShoulderTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			LeftShoulder.C0 = LeftShoulderC0 * LeftShoulderTilt

			RightHipTilt = RightHipTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			RightHip.C0 = RightHipC0 * RightHipTilt

			LeftHipTilt = LeftHipTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 10, 0), DefaultLerpAlpha)
			LeftHip.C0 = LeftHipC0 * LeftHipTilt
		elseif MoveDirection:Dot(Vector3.new(0,0,-1).Unit) > dotThreshold then
			-- print("Forwards")

			RootJointTilt = RootJointTilt:Lerp(CFrame.Angles(math.rad(-MoveDirection.Z) * 10, 0, 0), DefaultLerpAlpha)
			RootJoint.C0 = RootJointC0 * RootJointTilt



			RightShoulderTilt = RightShoulderTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			RightShoulder.C0 = RightShoulderC0 * RightShoulderTilt

			LeftShoulderTilt = LeftShoulderTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			LeftShoulder.C0 = LeftShoulderC0 * LeftShoulderTilt

			RightHipTilt = RightHipTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			RightHip.C0 = RightHipC0 * RightHipTilt

			LeftHipTilt = LeftHipTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			LeftHip.C0 = LeftHipC0 * LeftHipTilt
		elseif MoveDirection:Dot(Vector3.new(1,0,0).Unit) > dotThreshold then
			-- print("Right")

			RootJointTilt = RootJointTilt:Lerp(CFrame.Angles(0, 0, math.rad(-MoveDirection.X) * 35), DefaultLerpAlpha)
			RootJoint.C0 = RootJointC0 * RootJointTilt

		

			RightShoulderTilt = RightShoulderTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 15, 0), DefaultLerpAlpha)
			RightShoulder.C0 = RightShoulderC0 * RightShoulderTilt

			LeftShoulderTilt = LeftShoulderTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 15, 0), DefaultLerpAlpha)
			LeftShoulder.C0 = LeftShoulderC0 * LeftShoulderTilt

			RightHipTilt = RightHipTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 15, 0), DefaultLerpAlpha)
			RightHip.C0 = RightHipC0 * RightHipTilt

			LeftHipTilt = LeftHipTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 15, 0), DefaultLerpAlpha)
			LeftHip.C0 = LeftHipC0 * LeftHipTilt
		elseif MoveDirection:Dot(Vector3.new(0,0,1).Unit) > dotThreshold then
			-- print("Backwards")

			RootJointTilt = RootJointTilt:Lerp(CFrame.Angles(math.rad(-MoveDirection.Z) * 10, 0, 0), DefaultLerpAlpha)
			RootJoint.C0 = RootJointC0 * RootJointTilt



			RightShoulderTilt = RightShoulderTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			RightShoulder.C0 = RightShoulderC0 * RightShoulderTilt

			LeftShoulderTilt = LeftShoulderTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			LeftShoulder.C0 = LeftShoulderC0 * LeftShoulderTilt

			RightHipTilt = RightHipTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			RightHip.C0 = RightHipC0 * RightHipTilt

			LeftHipTilt = LeftHipTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			LeftHip.C0 = LeftHipC0 * LeftHipTilt
		elseif MoveDirection:Dot(Vector3.new(-1,0,0).Unit) > dotThreshold then
			-- print("Left")

			RootJointTilt = RootJointTilt:Lerp(CFrame.Angles(0, 0, math.rad(-MoveDirection.X) * 35), DefaultLerpAlpha)
			RootJoint.C0 = RootJointC0 * RootJointTilt



			RightShoulderTilt = RightShoulderTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 15, 0), DefaultLerpAlpha)
			RightShoulder.C0 = RightShoulderC0 * RightShoulderTilt

			LeftShoulderTilt = LeftShoulderTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 15, 0), DefaultLerpAlpha)
			LeftShoulder.C0 = LeftShoulderC0 * LeftShoulderTilt

			RightHipTilt = RightHipTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 15, 0), DefaultLerpAlpha)
			RightHip.C0 = RightHipC0 * RightHipTilt

			LeftHipTilt = LeftHipTilt:Lerp(CFrame.Angles(0, math.rad(-MoveDirection.X) * 15, 0), DefaultLerpAlpha)
			LeftHip.C0 = LeftHipC0 * LeftHipTilt
		elseif MoveDirection == Vector3.new(0, 0, 0) or script:GetAttribute("Toggle") == false then
			RootJointTilt = RootJointTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			RootJoint.C0 = RootJointC0 * RootJointTilt



			RightShoulderTilt = RightShoulderTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			RightShoulder.C0 = RightShoulderC0 * RightShoulderTilt

			LeftShoulderTilt = LeftShoulderTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			LeftShoulder.C0 = LeftShoulderC0 * LeftShoulderTilt

			RightHipTilt = RightHipTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			RightHip.C0 = RightHipC0 * RightHipTilt

			LeftHipTilt = LeftHipTilt:Lerp(CFrame.Angles(0, 0, 0), DefaultLerpAlpha)
			LeftHip.C0 = LeftHipC0 * LeftHipTilt
		end
	end
end

RunService.Heartbeat:Connect(UpdateDirectionalMovement)

local time = 1
local tweeninfo = TweenInfo.new(time/2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)

game.ReplicatedStorage.Tilt.Root.OnClientEvent:Connect(function(otherPlayer, RootJointCFrame)
	local Root = otherPlayer.Character:FindFirstChild("RootJoint", true)

	if Root then
		TweenService:Create(Root, tweeninfo, {C0 = RootJointCFrame}):Play()
	end
end)

game.ReplicatedStorage.Tilt.RightHip.OnClientEvent:Connect(function(otherPlayer, RightHipCFrame)
	local RightHip = otherPlayer.Character:FindFirstChild("Right Hip", true)

	if RightHip then
		TweenService:Create(RightHip, tweeninfo, {C0 = RightHipCFrame}):Play()
	end
end)

game.ReplicatedStorage.Tilt.LeftHip.OnClientEvent:Connect(function(otherPlayer, LeftHipCFrame)
	local LeftHip = otherPlayer.Character:FindFirstChild("Left Hip", true)

	if LeftHip then
		TweenService:Create(LeftHip, tweeninfo, {C0 = LeftHipCFrame}):Play()
	end
end)

game.ReplicatedStorage.Tilt.RightShoulder.OnClientEvent:Connect(function(otherPlayer, RightShoulderCFrame)
	local RightShoulder = otherPlayer.Character:FindFirstChild("Right Shoulder", true)

	if RightShoulder then
		TweenService:Create(RightShoulder, tweeninfo, {C0 = RightShoulderCFrame}):Play()
	end
end)

game.ReplicatedStorage.Tilt.LeftShoulder.OnClientEvent:Connect(function(otherPlayer, LeftShoulderCFrame)
	local LeftShoulder = otherPlayer.Character:FindFirstChild("Left Shoulder", true)

	if LeftShoulder then
		TweenService:Create(LeftShoulder, tweeninfo, {C0 = LeftShoulderCFrame}):Play()
	end
end)

local UpdateRate = 1/20

local Last1
while wait(UpdateRate) do
	game.ReplicatedStorage.Tilt.Root:FireServer(RootJointC0)
	game.ReplicatedStorage.Tilt.RightHip:FireServer(RightHipC0)
	game.ReplicatedStorage.Tilt.LeftHip:FireServer(LeftHipC0)
	game.ReplicatedStorage.Tilt.RightShoulder:FireServer(RightShoulderC0)
	game.ReplicatedStorage.Tilt.LeftShoulder:FireServer(LeftShoulderC0)
	print("WOKRING")
end

This is the ServerScriptService Script

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)

game.ReplicatedStorage.Tilt.Root.OnServerEvent:Connect(function(player, RootJointCFrame)
	for key, value in pairs(game.Players:GetChildren()) do
		if value ~= player and (value.Character.Torso.Position - player.Character.Torso.Position).Magnitude < 50 then
			game.ReplicatedStorage.Tilt.Root:FireClient(value, player, RootJointCFrame)
		end
	end
end)

game.ReplicatedStorage.Tilt.RightHip.OnServerEvent:Connect(function(player, RightHipCFrame)
	for key, value in pairs(game.Players:GetChildren()) do
		if value ~= player and (value.Character.Torso.Position - player.Character.Torso.Position).Magnitude < 50 then
			game.ReplicatedStorage.Tilt.RightHip:FireClient(value, player, RightHipCFrame)
		end
	end
end)

game.ReplicatedStorage.Tilt.LeftHip.OnServerEvent:Connect(function(player, LeftHipCFrame)
	for key, value in pairs(game.Players:GetChildren()) do
		if value ~= player and (value.Character.Torso.Position - player.Character.Torso.Position).Magnitude < 50 then
			game.ReplicatedStorage.Tilt.LeftHip:FireClient(value, player, LeftHipCFrame)
		end
	end
end)

game.ReplicatedStorage.Tilt.RightShoulder.OnServerEvent:Connect(function(player, RightShoulderCFrame)
	for key, value in pairs(game.Players:GetChildren()) do
		if value ~= player and (value.Character.Torso.Position - player.Character.Torso.Position).Magnitude < 50 then
			game.ReplicatedStorage.Tilt.RightShoulder:FireClient(value, player, RightShoulderCFrame)
		end
	end
end)

game.ReplicatedStorage.Tilt.LeftShoulder.OnServerEvent:Connect(function(player, LeftShoulderCFrame)
	for key, value in pairs(game.Players:GetChildren()) do
		if value ~= player and (value.Character.Torso.Position - player.Character.Torso.Position).Magnitude < 50 then
			game.ReplicatedStorage.Tilt.LeftShoulder:FireClient(value, player, LeftShoulderCFrame)
		end
	end
end)

	end)
end)


1 Like

It seems your trying to get the localplayer from the script in ServerScriptService if this script is a server side script then you are not able to get the local player, instead try this to get the player and the players character

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)
 player.CharacterAdded:Connect(function(character)
  -- your code here
 end)
end
2 Likes

It didn’t change anything. Also the server script was wrong I have no idea how I messed that up mb.

Are there any errors that are printing out in the console when you run the script?

No there is not, is it to do with the local script?

local Last1
while wait(UpdateRate) do
	game.ReplicatedStorage.Tilt.Root:FireServer(RootJointC0)
	game.ReplicatedStorage.Tilt.RightHip:FireServer(RightHipC0)
	game.ReplicatedStorage.Tilt.LeftHip:FireServer(LeftHipC0)
	game.ReplicatedStorage.Tilt.RightShoulder:FireServer(RightShoulderC0)
	game.ReplicatedStorage.Tilt.LeftShoulder:FireServer(LeftShoulderC0)
	print("WOKRING")
end
1 Like

is it printing this out successfully?

Yes, so I’m kinda stumped on this. Events and modules scripts are new to me.

can you elaborate on what “local server” means? i havent seen this term used before

Its to test multiplayer in roblox studio.
Screenshot 2024-06-24 225431

OHH, i see what you mean now. when you play it in a normal test does it work correctly?

Yes the characters dont tilt at all. I’ve copied their CFrame.C0 to the server script and a remote event but it doesn’t change their CFrame.C0 at all.

Maybe try passing the character over aswell to, as looping through each player every 1/20 of a second seems pretty resource heavy and unnecessary

When you say character do you mean the model in the workspace from the server script?

im talking about the localPlayer.Character

Sorry my brain isn’t working. How do I get the joint CFrames from the character? And should I send the remote events inside of it?