As you can see in the above video, the camera will not automatically return back to the original position. I am currently trying to make my own gun system and im stuck on recoil.
My recoil uses a spring module, specifically, this one:
I’ve tried many different solutions, none of which seemed to have worked. I’ve tried searching the forum for answers on the same or a similar topic, but none either has answers, or none resolve the issue.
My script is structured like so;
-- When script loads, create the spring
local RecoilSpring = Spring.fromFrequency(1, 30, 5)
FireGun():
-- Pushes the sping
RecoilSpring:AddVelocity(2)
GunEquipped():
-- Updates every frame while the weapon is equipped
task.spawn(function()
while Equipped do
Camera.CFrame *= CFrame.Angles(RecoilSpring.Offset, 0, 0)
RunService.PreRender:Wait()
end
end)
How do I properly resolve and correct this behavior?
Try using math.rad(RecoilSpring.Offset), if that doesn’t change it try changing your spring settings. If you make the range of your spring go from [-1,. 1], you can have an angle component somewhere defining the max rotation angle and do something like:
local maxAngle = math.rad(30)
-- Updates every frame while the weapon is equipped
task.spawn(function()
while Equipped do
Camera.CFrame *= CFrame.Angles(maxAngle*RecoilSpring.Offset, 0, 0)
RunService.PreRender:Wait()
end
end)
All math.rad would do is convert the number from degrees to radians, which just makes my offset value smaller, it doesn’t seem to change the fact that it still results in an offset, same goes for your max angle suggestion as all it does it multiply the number
I believe the issue lies with how springs work. You get this large initial offset, which seems to be the main cause of the issue when simply offsetting the camera CFrame
It has a range from around [-0.01, 0.025], which in radians would actually equate to a larger number in degrees (which is why i suggested that first fix). Anyways, the solution to this is to use a range preferably from [-1, 1] and multiply by a rotation component. That way, offset*rotation will give you an output in the range [-rotation, rotation].
You can use this graph here, I made it specifically for this module:
Also, make sure the method you use to rotate the camera correctly manipulates the camera. I have a tutorial on how to update the camera in the post for the module (examples section).
I’m struggling to get the values of -1 to 1 without offsetting it with an initial velocity.
Do I have to add an initial velocity somewhere? Or am I missing something? Also the examples you have aren’t really helpful to me as they appear to just directly overwrite values, except for this example here which uses a camera controller which seems to be helpful, and I have no idea how that works
function RenderStepped(dt)
if CurrentSpring then
CameraController.Properties.AdditionalRotation.Y = CurrentSpring.Offset;
else
CameraController.Properties.AdditionalRotation.Y = 0;
end
CameraController:Update();
end
task.wait(5)
local Spring = require(game.ReplicatedStorage.Spring)
local RunService = game:GetService("RunService")
local Camera = workspace.CurrentCamera
local recoilSpring = Spring.fromFrequency(1, 5, 2)
local initRot = Camera.CFrame.Rotation
recoilSpring:AddVelocity(16.5)
local maxAngle = math.rad(30)
RunService:BindToRenderStep("Camera", Enum.RenderPriority.Camera.Value + 1, function(dt)
Camera.CFrame *= CFrame.Angles(maxAngle*recoilSpring.Velocity*dt, 0, 0)
end)
-- OR
task.spawn(function()
local dt = 0
while Equipped do
Camera.CFrame *= CFrame.Angles(maxAngle*RecoilSpring.Velocity*dt, 0, 0)
dt = RunService.PreRender:Wait()
end
end)
Gives pretty good results in a blank baseplate test
Edit: you also need to stop updating the camera after the spring has a very low velocity. you could add a check for the velocity, something like
if ( recoilSpring.Velocity < 0.01 ) then
stopShowingRecoil()
end
Thanks! That seems to have worked pretty well. but how could I offset the camera positively only? i.e, no bouncing down towards the ground. Is that something I can do with a spring? Or would I have to come up with a different method? I’m trying to match the recoil on a previous gun system I used, but the code on that is a mess, but I do know for a fact it did use a spring