Camera Offset makes Character Shake

Hey DevForum! I had a weird and goofy question… when I am using a very generic first person camera with smooth movement and combining it with visible view models, my character seems to shake for no reason. It doesn’t matter if I’m using the smooth movement or not, the first person still bugs out. I found out the root cause of this to be “CameraOffset” in the humanoid, but I don’t know if there are any alternatives to fixing this. The X and Y values work fine on the offset, but not the Z (which is funnily enough the ONLY one that I need to work.)


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

local Player = Players.LocalPlayer
local Mouse = Player:GetMouse()
local Camera = workspace.CurrentCamera
local Humanoid = Player.Character:WaitForChild("Humanoid")
local Character = Player.Character

local bobbing = nil
local func1, func2, func3, func4 = 0, 0, 0, 0
local val, val2 = 0, 0
local int, int2 = 10, 10
local vect3 = Vector3.new()



UserInputService.MouseIconEnabled = true

local function lerp(a, b, c)
	return a + (b - a) * c
end

bobbing = RunService.RenderStepped:Connect(function(deltaTime)
	deltaTime = deltaTime * 30
	if Humanoid.Health <= 0 then
		bobbing:Disconnect()
		return
	end

	local rootMagnitude = Humanoid.RootPart and Vector3.new(Humanoid.RootPart.Velocity.X, 0, Humanoid.RootPart.Velocity.Z).Magnitude or 0
	local calcRootMagnitude = math.min(rootMagnitude, 25)

	if deltaTime > 1.5 then
		func1, func2 = 0, 0
	else
		func1 = lerp(func1, math.cos(tick() * 0.5 * math.random(5, 7.5)) * (math.random(2.5, 10) / 100) * deltaTime, 0.05 * deltaTime)
		func2 = lerp(func2, math.cos(tick() * 0.5 * math.random(2.5, 5)) * (math.random(1, 5) / 100) * deltaTime, 0.05 * deltaTime)
	end

	Camera.CFrame = Camera.CFrame * (CFrame.fromEulerAnglesXYZ(0, 0, math.rad(func3)) * CFrame.fromEulerAnglesXYZ(math.rad(func4 * deltaTime), math.rad(val * deltaTime), val2) * CFrame.Angles(0, 0, math.rad(func4 * deltaTime * (calcRootMagnitude / 5))) * CFrame.fromEulerAnglesXYZ(math.rad(func1), math.rad(func2), math.rad(func2 * 10)))

	val2 = math.clamp(lerp(val2, -Camera.CFrame:VectorToObjectSpace((Humanoid.RootPart and Humanoid.RootPart.Velocity or Vector3.new()) / math.max(Humanoid.WalkSpeed, 0.01)).X * 0.04, 0.1 * deltaTime), -0.12, 0.1)
	func3 = lerp(func3, math.clamp(UserInputService:GetMouseDelta().X, -2.5, 2.5), 0.25 * deltaTime)
	func4 = lerp(func4, math.sin(tick() * int) / 5 * math.min(1, int2 / 10), 0.25 * deltaTime)

	if rootMagnitude > 1 then
		val = lerp(val, math.cos(tick() * 0.5 * math.floor(int)) * (int / 200), 0.25 * deltaTime)
	else
		val = lerp(val, 0, 0.05 * deltaTime)
	end

	if rootMagnitude > 6 then
		int, int2 = 10, 9
	elseif rootMagnitude > 0.1 then
		int, int2 = 6, 7
	else
		int2 = 0
	end

	vect3 = lerp(vect3, Camera.CFrame.LookVector, 0.125 * deltaTime)
end)


Humanoid.StateChanged:Connect(function(newState, oldState)
	if newState == Enum.HumanoidStateType.Landed then

		local camEdit = Instance.new("CFrameValue")
		camEdit.Value = CFrame.new() * CFrame.Angles(math.rad(-0.75), 0, 0)

		local landedRecoil = TweenService:Create(camEdit, TweenInfo.new(0.15, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {Value = CFrame.new()})
		landedRecoil:Play()

		landedRecoil.Completed:Connect(function()
			landedRecoil:Destroy()

			camEdit.Value = CFrame.new() * CFrame.Angles(math.rad(0.225), 0, 0)

			local landedRecovery = TweenService:Create(camEdit, TweenInfo.new(0.6, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {Value = CFrame.new()})
			landedRecovery:Play()

			spawn(function()
				landedRecovery.Completed:Wait()
				landedRecovery:Destroy()
			end)
		end)

		spawn(function()
			for i = 1, 60 do
				Camera.CFrame = Camera.CFrame * camEdit.Value
				RunService.Heartbeat:Wait()
			end
		end)
	end
end)


function firstPerson()
	if Player.Character.Head.LocalTransparencyModifier == 1 then
		Player.Character["Right Arm"].LocalTransparencyModifier = 0
		Player.Character["Left Arm"].LocalTransparencyModifier = 0
		Player.Character["Right Leg"].LocalTransparencyModifier = 0
		Player.Character["Left Leg"].LocalTransparencyModifier = 0
		Player.Character["Torso"].LocalTransparencyModifier = 0
	end
end

game:GetService("RunService"):BindToRenderStep("FP", Enum.RenderPriority.Camera.Value, firstPerson)

--Getting rid of the shake would be just getting rid of lines 23-98. But I would like to have it *regardless*.

With Smooth Movement:

Without Smooth Movement:

Again they look virtually the same, which is why I don’t presume the issue to be the lerp.

Any help is appreciated and will be tested!

1 Like

Try with no scripts and see what’s the result

1 Like

With no scripts I would literally achieve nothing.

Just check if it still causes the avatar to do that (also the localtransparency thing)

From the third person perspective,
it seems to not spaz out.

From the first person perspective,
it still spazzes out.

this isn’t a solution but a suggestion:
there is no fixing the problem I ran into it once. when I tried to make a custom shift lock script.
and I’ve been questioning how Roblox make their shift lock script without getting that problem and I found out that they don’t use humanoid camera offset. the humanoid camera offset is kinda weird so don’t use it. if you want to make your camera offset but still want your character to move smoothly I suggest you read through Roblox’s shift lock script and try to replicate it or just edit it

I will try that in the morning. Ty!