I recently created this script that makes the character look up or down by modifying the Motor’s C0. This works but since its client sided only i decided to replicate the code into a server script and get the client to just send the current viewAngle.
Client side code:
local function MouseInputLoop()
local sensitivity = settingFolder.Sensitivity.Value
y += mouse.Value.X * BASE_SENSITIVITY * sensitivity
x = Clamp(x + mouse.Value.Y * BASE_SENSITIVITY * sensitivity, -MAX_LOOK_ANGLE, MAX_LOOK_ANGLE)
aimRemote:FireServer(x)
end
local function MotorLoop()
local moveVelocity = char.Humanoid:GetMoveVelocity()
local speed = moveVelocity.Magnitude
local roll = not char:GetAttribute("Aiming") and Clamp(charParts.RootPart.CFrame:VectorToObjectSpace(moveVelocity).X / char.Humanoid.WalkSpeed, -1, 1) * Rad(10) or 0
local pitch = speed > 0 and Clamp(charParts.RootPart.CFrame:VectorToObjectSpace(moveVelocity).Z / char.Humanoid.WalkSpeed, -1, 1) * Rad(10) or 0
leanSpring.Target = pitch
rollSpring.Target = roll
--Updates rootPart per frame to point with camera
local cf = CFrame.new(charParts.RootPart.CFrame.Position)
charParts.RootPart.CFrame = cf * CFrame.Angles(0, -y, 0)
local waistAngle = -x/2
--Makes torso move up and down based on camera
motors.Waist.C0 *= CFrame.Angles(waistAngle, 0, -rollSpring.Position)
--char.UpperTorso.Waist.Transform *= CFrame.Angles(-x, 0, 0)
motors.Neck.C0 *= CFrame.Angles(-x + x/2, 0, 0)
motors.Root.C0 *= CFrame.Angles(leanSpring.Position, 0, 0)
--moves camera to camera part
local camOffset = char:GetAttribute("CameraOffset")
local armAngle = x/2 - leanSpring.Position
motors.RightShoulder.C0 *= CFrame.Angles(-x + armAngle, 0, 0)
motors.LeftShoulder.C0 *= CFrame.Angles(-x + armAngle, 0, 0)
motors.Eyes.C0 = CFrame.new(charParts.Head.CFrame:ToObjectSpace(charParts.RootPart.CFrame):Inverse().Position) * camOffset * CFrame.Angles(-x, 0, -rollSpring.Position/2)
end
local function CameraLoop()
cam.CFrame = charParts.CamPart.CFrame
char.Head.LocalTransparencyModifier = 1
end
--Runs first, Reset motors from previous frame
runService:BindToRenderStep("ResetMotors", Enum.RenderPriority.Input.Value, function()
ResetMotors()
MouseInputLoop()
end)
--Runs second, modifies the motors depending on movement and where the player is looking
runService:BindToRenderStep("UpdateMotors", Enum.RenderPriority.Camera.Value, MotorLoop)
--Updates the camera after all motors were updated, including modifications done by the recoil profile
runService:BindToRenderStep("Render", Enum.RenderPriority.Last.Value, CameraLoop)
Server Side:
local aimConnection = game["Run Service"].Stepped:Connect(function()
smoothSpring.Target = char:GetAttribute("VerticalAngle")
local moveVelocity = char.Humanoid:GetMoveVelocity()
local speed = moveVelocity.Magnitude
local roll = not char:GetAttribute("Aiming") and math.clamp(char.HumanoidRootPart.CFrame:VectorToObjectSpace(moveVelocity).X / char.Humanoid.WalkSpeed, -1, 1) * math.rad(10) or 0
local pitch = speed > 0 and math.clamp(char.HumanoidRootPart.CFrame:VectorToObjectSpace(moveVelocity).Z / 20, -1, 1) * math.rad(10) or 0
leanSpring.Target = pitch
rollSpring.Target = roll
char.LowerTorso.Root.C0 = CFrame.new(char.LowerTorso.Root.C0.Position) * CFrame.Angles(leanSpring.Position, 0, 0)
local current = Vector3.new(char.UpperTorso.Waist.C0:ToOrientation())
char.UpperTorso.Waist.C0 = CFrame.new(char.UpperTorso.Waist.C0.Position) * CFrame.Angles(-smoothSpring.Position/2, current.Y, -rollSpring.Position)
char.Head.Neck.C0 = CFrame.new(char.Head.Neck.C0.Position) * CFrame.Angles(-smoothSpring.Position + smoothSpring.Position/2, 0, 0)
char.RightUpperArm.RightShoulder.C0 = CFrame.new(0.926, 0.548, 0.043) * CFrame.Angles(-smoothSpring.Position + smoothSpring.Position/2 - leanSpring.Position, 0, 0)
char.LeftUpperArm.LeftShoulder.C0 = CFrame.new(-0.926, 0.548, 0.043) * CFrame.Angles(-smoothSpring.Position + smoothSpring.Position/2 - leanSpring.Position, 0, 0)
end)
It replicates properly, but my issue is that the server’s motors are trying to overwrite the client’s, because of both sides fighting for the motors, it causes the gun to stutter between the server and client’s positions.
video:
In the video the arms dont look like theyre stuttering but you can see from the crosshair that it is, so when i fire the weapon it has a random chance of either firing from the client’s position or the server’s position.
Is there a way to stop the server from trying to overwrite the client? I need the server to replicate it because the weapon’s validation code requires the position of the muzzle, and if it didnt replicate, the server’s muzzle will always not closely match with the client’s.