Why does aiming down sights make my viewmodel jitter?

  1. What do you want to achieve?
    I want my viewmodel to be offset based on your aim

  2. What is the issue?
    My viewmodel keeps jittering when I try to aim down sights (I have lowered the update time from every frame to 0.1 seconds for testing purpose which shows what the viewmodel is having trouble with)

  3. What solutions have you tried so far?
    I have tried changing it from lerping between aiming and hip fire to going to aiming and hip fire instantly but the issue still wasn’t fixed.

--|| SERVICES ||--
local RunService = game:GetService("RunService")
local RepStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
--|| VARIBLES ||--
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Camera = workspace.CurrentCamera
local ViewModel = RepStorage.ViewModel:Clone()
local ViewModelRoot = ViewModel.PrimaryPart

local BobbleValue = Vector3.new(0,0,0)
local RotationValue = Vector3.new(0,0,0)
--|| FUNCTIONS ||--
function UpdateViewModel(dt)
	local HeadCFrame = Character.HumanoidRootPart.CFrame * CFrame.new(0,1.5,0)
	local Tool = Character:FindFirstChildOfClass("Tool")
	if (Camera.CFrame.Position - HeadCFrame.Position).Magnitude < 1 and Tool then
		ViewModel.Parent = Camera
		ViewModel.Torso["Left Shoulder"].Transform = Character.Torso["Left Shoulder"].Transform
		ViewModel.Torso["Right Shoulder"].Transform = Character.Torso["Right Shoulder"].Transform
		
		local AimingCFrame = CFrame.new(0,0,0)
		if Tool:FindFirstChild("AimAmount") then
			if Tool.AimAmount.Value > 0 then			
				AimingCFrame = AimingCFrame:Lerp(Camera.CFrame:ToObjectSpace(Tool.AimPart.CFrame),Tool.AimAmount.Value)
				AimingCFrame = CFrame.new(-AimingCFrame.Position.X,-AimingCFrame.Position.Y,0)
				print(AimingCFrame)
			end
		end
		
		ViewModelRoot.CFrame = Camera.CFrame  * AimingCFrame * CFrame.new(0, -1.5, -0.5) * CFrame.new(BobbleValue.X,BobbleValue.Y,BobbleValue.Z) * CFrame.Angles(math.rad(RotationValue.X),math.rad(RotationValue.Y),math.rad(RotationValue.Z))
		Character.Torso.ToolGrip.Part0 = ViewModel.Torso
	else
		ViewModel.Parent = nil
		Character.Torso.ToolGrip.Part0 = Character.Torso
	end
end
function UpdateVisualEffect(dt)
	local Bobble = Vector3.new(0, 0, 0)
	local Rotation = Vector3.new(0, 0, 0)
	if Character.Humanoid.MoveDirection.Magnitude > 0 then
		local BobbleX = math.cos(tick() * math.pi * 2) * .2
		local BobbleY = math.abs(math.sin(tick() * math.pi * 2)) * .2
		
		local RootSpaceDirection = Character.HumanoidRootPart.Position + Character.Humanoid.MoveDirection
		RootSpaceDirection = Character.HumanoidRootPart.CFrame:ToObjectSpace(CFrame.new(RootSpaceDirection.X,RootSpaceDirection.Y,RootSpaceDirection.Z))
		
		local RotateZ = -RootSpaceDirection.Position.X*15
		
		Bobble = Vector3.new(BobbleX-RootSpaceDirection.Position.X/2, -BobbleY, -RootSpaceDirection.Position.Z/2)
		Rotation = Vector3.new(0,0,RotateZ)
	end
	BobbleValue = BobbleValue:Lerp(Bobble,dt*10)
	RotationValue = RotationValue:Lerp(Rotation,dt*10)
end
function RenderStepped(dt)
	UpdateVisualEffect(dt)
	UpdateViewModel(dt)
end
--|| CONNECTIONS ||--
local idkbuttime = 0.1
while wait(idkbuttime) do
	RenderStepped(idkbuttime)
end
--RunService.RenderStepped:Connect(RenderStepped)

I don’t see any tweening in your script. Have you tried tweening the arms to the current location?

Tweening won’t work as a solution as my aimoffset isn’t static like some other fps games do it the value constantly changes based on the cframe of the aimpart

Fixed it by moving the AimingCFrame to after the cframe was set idk why it worked tho

function UpdateViewModel(dt)
	local HeadCFrame = Character.HumanoidRootPart.CFrame * CFrame.new(0,1.5,0)
	local Tool = Character:FindFirstChildOfClass("Tool")
	if (Camera.CFrame.Position - HeadCFrame.Position).Magnitude < 1 and Tool then
		ViewModel.Parent = Camera
		ViewModel.Torso["Left Shoulder"].Transform = Character.Torso["Left Shoulder"].Transform
		ViewModel.Torso["Right Shoulder"].Transform = Character.Torso["Right Shoulder"].Transform
		
		ViewModelRoot.CFrame = Camera.CFrame * CFrame.new(0, -1.5, -0.5) * CFrame.new(BobbleValue.X,BobbleValue.Y,BobbleValue.Z) * CFrame.Angles(math.rad(RotationValue.X),math.rad(RotationValue.Y),math.rad(RotationValue.Z))
		
		local AimingCFrame = CFrame.new(0,0,0)
		if Tool:FindFirstChild("AimAmount") then
			if Tool.AimAmount.Value > 0 then			
				local NewAimCFrame = Camera.CFrame:ToObjectSpace(Tool.AimPart.CFrame)
				AimingCFrame = CFrame.new(-NewAimCFrame.Position.X, -NewAimCFrame.Position.Y, -2)
			end
		end
		
		ViewModelRoot.CFrame *= AimingCFrame
		
		Character.Torso.ToolGrip.Part0 = ViewModel.Torso
	else
		ViewModel.Parent = nil
		Character.Torso.ToolGrip.Part0 = Character.Torso
	end
	
end