For my recoil, I use a camera module used for a gun kit. As good as it is, the problem is that when players have low frame rate they have super high recoil making it unplayable. I have tried to use deltaTime to get around this but it still occurs.
local physics = require(script.PhysicsModule)
local cam = {}
cam.__index = cam
local cams = {}
local lTick = tick()
local function updatecam(v,dt)
local x,y,z = v.recoil.x.p(),v.recoil.y.p(),v.recoil.z.p()
local n = dt * 100
x,y,z = x*n,y*n,z*n
v.current.CoordinateFrame = v.current.CoordinateFrame*CFrame.Angles(x,y,z)
end
function cam.new(setting)
local nCam = {}
nCam.current = workspace.CurrentCamera
nCam.angles = {}
nCam.angles.x = 0
nCam.angles.y = 0
nCam.angles.z = 0
nCam.recoil = {}
nCam.recoil.x = physics.spring.new{d=setting.RecoilDamper;s=setting.RecoilSpeed;}
nCam.recoil.y = physics.spring.new{d=setting.RecoilDamper;s=setting.RecoilSpeed;}
nCam.recoil.z = physics.spring.new{d=setting.RecoilDamper;s=setting.RecoilSpeed;}
table.insert(cams,nCam)
return setmetatable(nCam,cam)
end
function cam:accelerate(x,y,z)
self.recoil.x.impulse(x)
self.recoil.y.impulse(y)
self.recoil.z.impulse(z)
end
function cam:accelerateXY(x,y)
self.recoil.x.impulse(x)
self.recoil.y.impulse(y)
end
function cam:disconnect()
for i,v in pairs(cams) do
if v == self then
table.remove(cams,i)
self = nil
break
end
end
end
game:GetService("RunService"):BindToRenderStep("RecoilCam",2000,function(dt)
local cDT = tick() - lTick
for _,v in pairs(cams) do
updatecam(v,cDT)
end
lTick = tick()
end)
return cam
PhysicsModule
local physics = {}
local tick = tick
local setmt = setmetatable
local sin = math.sin
local cos = math.cos
local atan2 = math.atan2
local tan = math.tan
local e = 2.718281828459045
local os = os
physics.spring = {}
function physics.spring.new(data)
local c0,c1
local t0
local d,s
local target
local cd
if data then
c0,c1=0,0
t0=os.clock()
d,s=data.d,data.s
target=0
cd=0
else
c0,c1=0,0
t0=os.clock()
d,s=1,1
target=0
cd=0
end
local function position()
local t=os.clock()
local sx=s*(t-t0)
if d==1 then
return (c0+c1*sx)/e^sx+target
else
return (c0*cos(cd*sx)+c1*sin(cd*sx))/e^(d*sx)+target
end
end
local function velocity()
local t=os.clock()
local sx=s*(t-t0)
if d==1 then
return (c1*(s-sx)-c0)/e^sx
else
return s*((cd*c1-c0*d)*cos(cd*sx)-(cd*c0+c1*d)*sin(cd*sx))/e^(d*sx)
end
end
return {
target=function(newtarget,newd,news)
news=news or s
local p0,v0=position(),velocity()/news
d=newd or d
t0=os.clock()
target=newtarget
c0=p0-target
if d==1 then
c1=v0+c0
else
cd=(1-d*d)^0.5
c1=(v0+c0*d)/cd
end
s=news
end;
impulse=function(v)
local p0,v0=position(),(velocity()+v)/s
t0=os.clock()
c0=p0-target
if d==1 then
c1=v0+c0
else
cd=(1-d*d)^0.5
c1=(v0+c0*d)/cd
end
end;
p=position;
v=velocity;
}
end
function physics.trajectory(sx,sy,sz,v,px,py,pz)
local g=9.81*40
local dx,dy,dz=px-sx,py-sy,pz-sz
local d=(dx*dx+dz*dz)^0.5
local th=atan2(v*v-(v*v*v*v-g*(g*d*d+2*dy*v*v))^0.5,g*d)
return px,sy+d*tan(th),pz
end
Have you tried using the dt argument returned from renderstepped instead of cdt? Dt would likely be more reliable for your line that makes it proportional across fps’.
I found that it didn’t really make a difference. In the past before i had updated it it was the other way around, where ifyou had high fps (fps unlocker) you would have insane recoil.
I found nothing wrong with your direct FPS normalizer thingy, so its not that
Other potential causes would be not using the correct rate for the time given, the spring thing bugging out at higher recoil values to make up for the lack of rate, or just a placebo effect from the recoil being in higher “chunks” at lower framerates.
It might be helpful to specify the framerates at which this becomes an issue, or a video of the issue, however I cant guarantee Id be able to make any sense of it.
Maybe try bypassing the physics module and seeing what happens. In my testing I bypassed the physics module cause I have no idea how it works either, but you might want to test it in the full context of your game.
I think I have it: to get a proper ratio, try setting n to this:
local n = (1 / dt) * 60
By doing that, players with 60 fps will get 1x the recoil, players with 120 fps will get double the recoil, and players with 30 fps will get half the recoil. It is kind of strange however that the lower FPS client is seeing higher recoil, it would make more sense by being the other way around.