Hello, DevForum.
I’m having an issue with a spring module I’m using for procedurally animated effects in my FPS game.
You see, whenever I run the game in 60FPS, the recoil is essentially 1x. When I run it in 120FPS, it’s doubled. This is extremely troublesome, especially for people who leave their FPS entirely uncapped. I accidentally joined my game where I had 1000fps, and the recoil made it unplayable.
I’ve tried many things, including passing in the ‘dt’ into the function, however it doesn’t seem to do anything.
Here is the spring module:
-- Constants
local ITERATIONS = 8
-- Module
local SPRING = {}
-- Functions
function SPRING.new(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.getstats(self)
return self.Mass, self.Force, self.Damping, self.Speed
end
function spring.changestats(self, mass, force, damping, speed)
self.Mass = mass or self.Mass
self.Force = force or self.Force
self.Damping = damping or self.Damping
self.Speed = speed or self.Speed
end
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 = 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
return spring
end
-- Return
return SPRING
And here is a snippet of the code responsible for using the spring module to update the recoiled viewmodel:
local cameraRecoil = self.CameraRecoilSpring:update(dt)
local viewmodelRecoil = self.ViewmodelRecoilSpring:update(dt)
self.Camera.CFrame *= CFrame.Angles(cameraRecoil.X, cameraRecoil.Y, cameraRecoil.Z)
self.Viewmodel.HumanoidRootPart.CFrame *= CFrame.Angles(viewmodelRecoil.X, viewmodelRecoil.Y, viewmodelRecoil.Z)
The above code is run in a ‘BindToRenderStep’ event where it gets the dt variable from.