Recoil being affected by high FPS

I’ve been continuing progress on my first person shooter, but i’ve run into an unusual problem,

Whenever i play in high FPS (around 120fps or higher), the camera recoil goes insane when i shoot, and the viewmodel.

I’m not sure what to do in all honesty, i could play with deltatime but i’m not sure how to quite do that, and i’ve heard it doesn’t make a difference, so what could i possibly do?

Module Script:

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
	
	viewmodel:SetPrimaryPartCFrame(workspace.Camera.CFrame)
	
	
	local Bobble = Vector3.new(GetBobbing(10), GetBobbing(5), GetBobbing(5))
	local MouseDelta = game:GetService("UserInputService"):GetMouseDelta()
	
	local Character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
	
	BobbleSpring:shove(Bobble / 10 * (Character.HumanoidRootPart.Velocity.Magnitude) / 10)
	SwaySpring:shove(Vector3.new(-MouseDelta.X / 75, MouseDelta.Y / 75, 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


function module.Shoot(Mouse, FirePos, FireCF, Attachment, RecoilSpring, Up, Sideways, Shake, Gun)
	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, math.random(-Sideways, Sideways), Shake)) -- Vector3.new(up, sideways, shake) // remember
		coroutine.wrap(function()
			task.wait(.1)
			RecoilSpring:shove(Vector3.new(-(Up - .2), math.random(-(Sideways / 2), (Sideways / 2)), -Shake))
		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, math.random(-Sideways, Sideways), Shake)) -- Vector3.new(up, sideways, shake) // remember
		coroutine.wrap(function()
			task.wait(.1)
			RecoilSpring:shove(Vector3.new(-(Up - .2), math.random(-(Sideways / 2), (Sideways / 2)), -Shake))
		end)()
	end
end

Local Script (inside weapon tool)

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

are you sure that u used the delta time corectly

1 Like

what are these functions? pls. send I think that could be the bug

2 Likes

Im using :update on the springs using a spring module

1 Like

are you sure you use the delta there

1 Like

yes, dt = DeltaTime

as i’ve shown here…

1 Like

not there here

in these functions

1 Like

yep, im using delta, im sure [characters]

1 Like

Sadly I am not an gun system expert so I think i can’t really help you

1 Like

no problem, thanks anyway mate!

2 Likes

maybe with server deltatime? (RunService.Heartbeat)

1 Like

that just made it much more worse…

1 Like

do you multiply or divide by delta time?
because you want to multiply by deltatime

1 Like

all i do with delta time is use it to update the springs
this is what happens in the spring module when i update

function spring.update(self, dt)
		local scaledDeltaTime = dt * self.Speed / ITERATIONS
		for i = 1, ITERATIONS do
			local iterationForce= self.Target - self.Position
			local acceleration	= (iterationForce * self.Force) / self.Mass

			acceleration		= acceleration - self.Velocity * self.Damping

			self.Velocity	= self.Velocity + acceleration * scaledDeltaTime
			self.Position	= self.Position + self.Velocity * scaledDeltaTime
		end

		return self.Position
	end
1 Like

if I’m not wrong, the render step is affected by the player’s FPS, so a higher fps increases the number of times the event is called. Do you do anything to combat it?

1 Like

No, that’s the issue, I’m trying to find a solid fix to this FPS issue

What is the speed and iterations?

Character minimum blablkablabala

1 Like

iterations is 8
speed is 4

characteraaaaaa

1 Like

Try using the tick variable and check it for 60 fps.

This locks it to 60 fps,
Change “fps” to any given fps

Ex:

local fps = 60
local fpsDelay = 1/fps
local fpsTick = tick()

RunService.RenderStepped:Connect(function(dt)
       if tick() >= fpsTick+fpsDelay then
              fpsTick = tick()
              --Run recoil code
       end

       --Other stuff
end)
1 Like

you could try math.clamp to limit the max values that can be used for the recoil

1 Like