Quenty's spring module dependent on fps no matter what I do

Ive tried absolutely everything. Ive multiplied everything by dt, ive used heartbeat, i used heartbeat from server, ive used a while loop, ive used accumulators. i tried using only the difference for spring position, nothing. nothing works and im pretty sure its an issue with the module itself. ive tried timeskipping by dt, still nothing.

tl;dr if anyone can provide an example of what they did for their recoil systems using springs that would be great.

and recommend me a different module or something because quenty’s spring module is dependent on fps no matter what. i think its how it calculates deltatime itself is busted and im not fixing it. even deepseek cant figure out how to fix it.

Using while loop with task.wait, still affected.

task.spawn(function()
	task.wait(5)
	while task.wait(0.01) do
		client:Update(0.01)
		client:Heartbeat(0.01)
	end
end)

task.wait does not have to wait the time you specified. You are assuming it takes 0.01 and then updating by that much. That’s already framerate dependent.
image

1 Like

Adding on to azqjanna’s reply, you can get the amount that task.wait waited using the return value from it.

You can also just connect it to RunService.RenderStepped and use the deltaTime parameter (probably more common). (Edit: I didn’t see you had already tried Heartbeat.)

ok great, but that doesnt matter i only used that as a test to see where the issue is. yes obviously i used renderstep before this :man_facepalming:

1 Like

You could try using x_o’s spring module. BIackShibe uses that one and it seems fine.

Here is BlackShibe’s copy (I bet the real one is on GitHub or something):

I’d have to see your code for updating the spring to determine what’s going on. I’ve used Quenty’s spring in the past, and I’ve never noticed this problem.

Edit: Actually x_o’s module might need to be modified. Here is a modified version that’s meant to be framerate independent:

-- step == 1/60
	self.totaltime = math.min(1,self.totaltime+dt)
	while self.totaltime >= self.step do
		self.totaltime -= self.step
		self.springs.modelRot:shove(Vector3.new(sinHelper(10,1,0.03),sinHelper(5,1,0.03),0)*dt*velocity.Magnitude*bobMod*3)
		if self.equippedType == "gun" then
			self.gun.Update()
		end	
		viewmodel:PivotTo(
			(camera.CFrame * self.offsets.modelCurrent * self.offsets.constant)
				* CFrame.Angles(modelRot.x, modelRot.y, 0)
				* CFrame.new(0,-modelRot.x*1.53,modelRot.z)
			- camera.CFrame.UpVector * 1.5
		)
		camera.CFrame = camera.CFrame * CFrame.Angles(cameraRot.x, cameraRot.y, cameraRot.z)
	end

using blackshibe spring

same result.

1 Like

Could you try the modified one? Based on that thread it looks like x_o’s/the blackshribe one is also framerate dependent.

It should have the same interface as the blackshribe one.

-- step == 1/60
	self.totaltime = math.min(1,self.totaltime+dt)
	while self.totaltime >= self.step do
		self.totaltime -= self.step
		self.springs.modelRot:Shove(Vector3.new(sinHelper(10,1,0.03),sinHelper(5,1,0.03),0)*velocity.Magnitude*bobMod*3)
		if self.equippedType == "gun" then
			self.gun.Update()
		end	
		viewmodel:PivotTo(
			(camera.CFrame * self.offsets.modelCurrent * self.offsets.constant)
				* CFrame.Angles(modelRot.x, modelRot.y, 0)
				* CFrame.new(0,-modelRot.x*1.53,modelRot.z)
			- camera.CFrame.UpVector * 1.5
		)
		camera.CFrame = camera.CFrame * CFrame.Angles(cameraRot.x, cameraRot.y, cameraRot.z)
	end

gunclient

gun.client.springs.cameraRot:Shove( 
		Vector3.new(recoil[1],recoil[2],math.random(-5,5))*0.01
	)
	gun.client.springs.modelRot:Shove( 
		Vector3.new( 
			math.random( mrecoil[1][1], mrecoil[1][2] ), 
			math.random( mrecoil[2][1], mrecoil[2][2] ),
			math.random( mrecoil[3][1], mrecoil[3][2] )
		)
			* mrecoil[4]
	)

i removed the *dt because it didnt do anything

same effect.

dont think there is a solution to this honestly ive had this issue ever since ive made fps guns. never fixed it, terrible at math so i probably will never fix it. will just have this as a feature until i can steal someone elses code.

1 Like
	task.wait(5)
	while task.wait(0.01) do
		client:Update(0.01)
		client:Heartbeat(0.01)
	end
end)

Perhaps try this?

local THIS_FPS = 60
task.spawn(function()
	task.wait(5)
    dt = task.wait(0.01)
	while true do
		client:Update(dt * THIS_FPS)
		client:Heartbeat(dt * THIS_FPS)
	end
end)

EDIT: Didn’t see you already tried dt; if you have, chances are it’s the module itself, not you. You’ll have to dig in and fix it, but it should only be a matter of multiplying every FPS-dependent operation by dt times whatever frame rate you want to maintain

1 Like

Is the problem perhaps that the number of shoves you’re giving is framerate dependent?

It looks like that code might be running every frame based on the step stuff.

1 Like

step stuff is supposed to lock it to 60 times a second.

1 Like