Viewmodel behaving strange

I want the client to have a smooth viewmodel and allow other players to also see that viewmodel at the same smoothness the client sees it at.

The clients viewmodel has no problems as far as I can see but when another client tries to replicate the viewmodels smoothness, it lags and is delayed.

I’ve been trying to solve this issue for quite a bit so any help would be great.

Viewmodel lagging:

External Media

Clients ViewModel Script:

local player = game.Players.LocalPlayer
local character = player.Character

local id = player.UserId

local humanoid = character.Humanoid

local viewmodel = script.Parent.ViewModel.Value

local plrAnimator = character.Humanoid.Animator

local vmAnimator = viewmodel.Humanoid.Animator

local Camera = game.Workspace.CurrentCamera

local loadedAnimations = {}

local aimCF = CFrame.new()

viewmodel["Left Arm"].CastShadow = false
viewmodel["Right Arm"].CastShadow = false

local TweenService = game:GetService("TweenService")
local TweenTime = 0.3 -- Amount of time for transmission
local startTime = 0.5
local Intensity = 0.25
local lastState = 0
local t = tick()



local function update(dt)
	
	script.Update:FireServer(game.Workspace.CurrentCamera.CFrame,dt)
	
	local aiming = script.Parent.Aiming.Value
	
	local RunService = game:GetService('RunService')
	local Spring = require(script:WaitForChild('Spring'))

	local SwaySpring = Spring.new()
	local BobSpring = Spring.new()

	local function Bob(addition)
		return math.sin(tick() * addition * 1.3) * 0.5
	end

	local Player = game:GetService('Players').LocalPlayer
	local Character = Player.Character or Player.CharacterAdded:Wait()
	

	
	if aiming == true then
		local offset = viewmodel.AimPart.CFrame:ToObjectSpace(viewmodel.Head.CFrame)
		aimCF  = aimCF:Lerp(offset,.1)
	else
		local offset = CFrame.new()
		aimCF = aimCF:Lerp(offset,.1)
	end


		-- Get mouse velocity
		local Delta = game.UserInputService:GetMouseDelta()

		-- Shoving
		SwaySpring:shove(Vector3.new(-Delta.X/30, Delta.Y/30, 0))
		BobSpring:shove(Vector3.new(Bob(5), Bob(10), Bob(5)) / 10 * (Character.PrimaryPart.Velocity.Magnitude) / 2)

		-- Updating springs
		local UpdatedSway = SwaySpring:update(dt)
		local UpdatedBob = BobSpring:update(dt)

		-- Applying springs
		viewmodel:PivotTo(
			CFrame.new(Character.PrimaryPart.Position) * workspace.CurrentCamera.CFrame.Rotation *
				CFrame.new(UpdatedSway.X, UpdatedSway.Y, 0) *
				CFrame.new(UpdatedBob.X, UpdatedBob.Y, 0) * CFrame.new(0,0,0) * aimCF
		)
		
	
--viewmodel.Torso["Left Shoulder"].Transform = character.Torso["Left Shoulder"].Transform
	--viewmodel.Torso["Right Shoulder"].Transform = character.Torso["Right Shoulder"].Transform
end



for _, part in viewmodel:GetDescendants() do
	if part:IsA("Accessory") then
		part:Destroy()
	end

	if part:IsA("Decal") then
		part:Destroy()
	end
end

viewmodel["Torso"].Transparency = 1

viewmodel["Torso"].CollisionGroup = "Players"
viewmodel["Left Arm"].CollisionGroup = "Players"
viewmodel["Right Arm"].CollisionGroup = "Players"

local con = game:GetService("RunService"):BindToRenderStep("ViewModel", Enum.RenderPriority.Camera.Value + 1, function(dt)
	
	update(dt)

end)

character.Humanoid.Died:Connect(function()
	con:Disconnect()
	viewmodel:Destroy()
end)

character.DescendantAdded:Connect(function(obj)

	if obj.Name == "BodyAttach" then
		task.wait()
		character.Torso.ToolGrip.Part0 = viewmodel.Torso
	end
end)

Other clients attempting to replicate viewmodel script:

local aimCF = CFrame.new(0,0,0)

game.ReplicatedStorage.Transform_ViewModel_Arms.OnClientEvent:Connect(function(viewmodel,character)
	
	viewmodel:FindFirstChild("Torso")["Left Shoulder"].Transform = character:FindFirstChild("Torso")["Left Shoulder"].Transform
	viewmodel:FindFirstChild("Torso")["Right Shoulder"].Transform = character:FindFirstChild("Torso")["Right Shoulder"].Transform

end)

game.ReplicatedStorage.Follow_ViewModel_Arms.OnClientEvent:Connect(function(camera,dt,character,viewmodel,Delta)



		local aiming = character.Aiming.Value

		local RunService = game:GetService('RunService')
		local Spring = require(script:WaitForChild('Spring'))

		local SwaySpring = Spring.new()
		local BobSpring = Spring.new()

		local function Bob(addition)
			return math.sin(tick() * addition * 1.3) * 0.5
		end
		local Character = character



		if aiming == true then
			local offset = viewmodel.AimPart.CFrame:ToObjectSpace(viewmodel.Head.CFrame)
			aimCF  = aimCF:Lerp(offset,.1)
		else
			local offset = CFrame.new()
			aimCF = aimCF:Lerp(offset,.1)
		end


	-- Get mouse velocity * CFrame.new(Character.Humanoid.MoveDirection)

		-- Shoving
		SwaySpring:shove(Vector3.new(-Delta.X/30, Delta.Y/30, 0))
		BobSpring:shove(Vector3.new(Bob(5), Bob(10), Bob(5)) / 10 * (Character.PrimaryPart.Velocity.Magnitude) / 2)

		-- Updating springs
		local UpdatedSway = SwaySpring:update(dt)
		local UpdatedBob = BobSpring:update(dt)

		-- Applying springs
	viewmodel:PivotTo(CFrame.new(Character.PrimaryPart.Position) * camera.Rotation  * CFrame.new(UpdatedSway.X, UpdatedSway.Y, 0) * CFrame.new(UpdatedBob.X, UpdatedBob.Y, 0) * CFrame.new(0,0,0) * aimCF)


end)

please excuse the horrid code

I wonder why :thinking:


reason:
ping.
solution:
make atleast the position be always attached to the character and only send the orientation it should be at and if the player is aiming

how would I go about doing that?

using welds

I did try that but it turns my entire character with the camera, ill try it out again though.

sorry to bug you again mate but I tried to rotate the welds c0 with the cameras rotation but the viewmodel just spins infinitely, know a fix?

you are adding the orientation instead of replacing it (probably)