Recoil using springs isn't frame independent

This code was taken from BlackShibes uncopylocked FPS game.
On high FPS, the spring shove is too strong. I have no idea why considering the recoil works fine in the other game.
I’ve also noticed it takes a while for the shove back in the opposite direction of the recoil. Which you can see in the video.

function recoil(dt)
	recoilSpring:shove(Vector3.new(0.03, 0, 0) * dt * 60)
	task.delay(0.15, function()
		recoilSpring:shove(Vector3.new(-0.03, 0, 0) * dt * 60)
	end)
end

function onUpdate(dt)
	if isFiring then
		recoil(dt)
	end
	local recoilPos= recoilSpring:update(dt)
	
	camera.CFrame = camera.CFrame * CFrame.Angles(recoilPos.x, recoilPos.y, recoilPos.z)
end


RunService.RenderStepped:Connect(onUpdate)

The spring module I’m using

-- Constants

local ITERATIONS = 8

-- Module

local SPRING = {}

-- Functions

function SPRING.create(self, mass, force, damping, speed)
	local spring = {
		Target = Vector3.new(),
		Position = Vector3.new(),
		Velocity = Vector3.new(),

		Mass = mass or 5,
		Force = force or 50,
		Damping = damping or 4,
		Speed = speed or 4,
	}

	function spring.shove(self, force)
		local x, y, z = force.X, force.Y, force.Z
		if x ~= x or x == math.huge or x == -math.huge then
			x = 0
		end
		if y ~= y or y == math.huge or y == -math.huge then
			y = 0
		end
		if z ~= z or z == math.huge or z == -math.huge then
			z = 0
		end
		self.Velocity = self.Velocity + Vector3.new(x, y, z)
	end

	function spring.update(self, dt)
		local scaledDeltaTime = math.min(dt, 1) * self.Speed / ITERATIONS

		for _ = 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

	return spring
end

-- Return

return SPRING

I’ve found that limiting deltaTime like this works and stops the difference in different FPS recoil.
But I still can’t figure out how I could make the recoil look nice without that really long delay in recovery as seen in the video.

local Accumulated = 0
local Rate = 1/60 -- 60 times a second

function onUpdate(dt)
	if isFiring then
		recoil(dt)
	end
	local recoilPos = recoilSpring:update(dt)
	
	Accumulated += dt
	if Accumulated >= Rate then
		Accumulated -= Rate
		
		camera.CFrame *= CFrame.Angles(math.rad(recoilPos.X),0,0)
	end
end
1 Like

you want it to be faster or slower ? , i do not think i understand what do you mean

bump
lorem ipsum dolor sit amet