Players camera glitches when shooting upwards

I’m working on an FPS game with viewmodels like most FPS games, Although i’ve run into a problem that’s quite unusual.

Whenever i shoot upwards, the cameras rotation sort of glitches out, this is probably due to the recoil, im using the spring module by the way.

Here’s a video of what’s happening

Here’s the module script im using to move the camera using recoil (not the spring module):

function module.update(viewmodel, dt, RecoilSpring, BobbleSpring, SwaySpring)
	
	for i,v in pairs(viewmodel:GetChildren()) do
		if v:IsA("MeshPart") or v:IsA("Part") then
			v.CanCollide = false
		end
	end
	
	local Bobble = Vector3.new(GetBobbing(10) * dt, GetBobbing(5) * dt, GetBobbing(5) * dt)
	local MouseDelta = game:GetService("UserInputService"):GetMouseDelta()

	local Character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
	
	viewmodel:SetPrimaryPartCFrame(workspace.CurrentCamera.CFrame)

	BobbleSpring:shove(Bobble / 10 * (Character.HumanoidRootPart.Velocity.Magnitude) / 10)
	SwaySpring:shove(Vector3.new(-MouseDelta.X / 1.5 * dt, MouseDelta.Y / 1.5 * dt, 0))

	local UpdatedRecoilSpring = RecoilSpring:update(dt)
	local UpdatedBobbleSpring = BobbleSpring:update(dt)
	local UpdatedSwaySpring = SwaySpring:update(dt)

	viewmodel:SetPrimaryPartCFrame(viewmodel:GetPrimaryPartCFrame():ToWorldSpace(CFrame.new(UpdatedBobbleSpring.Y, UpdatedBobbleSpring.X, 0)))
	viewmodel:SetPrimaryPartCFrame(viewmodel:GetPrimaryPartCFrame() * CFrame.new(UpdatedSwaySpring.X, UpdatedSwaySpring.Y, 0))

	viewmodel:SetPrimaryPartCFrame(viewmodel:GetPrimaryPartCFrame() * CFrame.Angles(math.rad(UpdatedRecoilSpring.X), math.rad(UpdatedRecoilSpring.Y), 0))
	workspace.Camera.CFrame *= CFrame.Angles(math.rad(UpdatedRecoilSpring.X), math.rad(UpdatedRecoilSpring.Y), math.rad(UpdatedRecoilSpring.Z))
end

Here’s where I run the .update (Gun Local Script):

RunService.RenderStepped:Connect(function(dt)
	if Viewmodel then
		MainModule.update(Viewmodel, dt, RecoilSpring, BobbleSpring, SwaySpring)
	end
end)

And this is where i use :shove when i shoot for the recoil (Same Module Script):

function module.Shoot(Mouse, FirePos, FireCF, Attachment, RecoilSpring, Up, Sideways, Shake, Gun, dt)
	local plr = game.Players.LocalPlayer
	
	local Cam = workspace.CurrentCamera
	local Viewmodel = Cam:WaitForChild(Gun.Name)
	
	local Ammo = Gun:GetAttribute("Ammo")
	local OrgAmmo = Gun:GetAttribute("OriginalAmmo")
	
	local RS = game:GetService("ReplicatedStorage")
	local SS = game:GetService("SoundService")
	
	local KillSound = SS:WaitForChild("KillSound")
	local EXPsound = SS:WaitForChild("EXP")
	
	local Background = plr.PlayerGui.Kill.Background
	local KillPopup = plr.PlayerGui.Kill.KillPopup
	local HeadPopup = plr.PlayerGui.Kill.HeadPopup
	
	FirePos = Attachment.Position
	FireCF = Attachment.CFrame

	if Mouse.Target ~= nil then

		local ShootEvent = RS.Events.Shoot:InvokeServer(Mouse.Hit.Position, false, FirePos, FireCF, Gun)
		
		print(ShootEvent)
		
		RecoilSpring:shove(Vector3.new(Up * dt, math.random(-Sideways, Sideways) * dt, Shake * dt)) --!!! Here
		coroutine.wrap(function()
			task.wait(.1)
			RecoilSpring:shove(Vector3.new(-(Up - .2) * dt, math.random(-(Sideways / 2), (Sideways / 2)) * dt, -Shake * dt)) --!!! Here
		end)()
		
		if ShootEvent == "Killed" then
			KillSound:Play()
			
			Kill_UI(Background, KillPopup)

			EXPsound:Play()
		end
		
		if ShootEvent == "Headshot" then
			KillSound:Play()
			
			Kill_UI(Background, HeadPopup)

			EXPsound:Play()
		end
		
	else
		RS.Events.Shoot:InvokeServer(Mouse.Hit.Position, true, FirePos, FireCF, Gun)
		
		RecoilSpring:shove(Vector3.new(Up * dt, math.random(-Sideways, Sideways) * dt, Shake * dt)) --!!! Here
		coroutine.wrap(function()
			task.wait(.1)
			RecoilSpring:shove(Vector3.new(-(Up - .2 * dt), math.random(-(Sideways / 2), (Sideways / 2)) * dt, -Shake * dt)) --!!! Here
		end)()
	end
end

I run the .Shoot in that same Gun Local Script but i don’t believe it’s necessary to provide it, unless i’m wrong.

I’ve never run into this before, so help would be very useful!

2 Likes

Im confused what exactly is happening in the video, can you rerecord the problem with the games audio?