How to make good gun recoil?

I’m coding a gun system for my game, and I came across this issue that I’m having with every solution that I can find on the internet or some are very jumpy, not good.

I’ve been using TweenService, for smooth transitions, but it snaps down very sharply and is not smooth. Me using Button1Down, is just an experiment to test different recoils and seeing what I like (it doesn’t matter if I put it in the gun system or not).

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")

local player = Players.LocalPlayer

local mouse = player:GetMouse()
local camera = workspace.CurrentCamera

local RecoilCFrame = CFrame.Angles(0, 0, 0)
mouse.Button1Down:Connect(function()
	local recoilPattern23 = workspace.CurrentCamera.CFrame * CFrame.Angles(0.01, 0, 0)
	local tweeninfo = TweenInfo.new(.91, Enum.EasingStyle.Linear)
	TweenService:Create(workspace.CurrentCamera, tweeninfo, {CFrame = recoilPattern23}):Play()
end)
1 Like

Keyframe animations are probably the best solution to this, because they are the smoothest and most realistic. I know some people aren’t that good at animating but yeah.

1 Like

You can move the camera with animations? Never knew this, do you have good documentation or video about this? I’ve always knew that you could move character parts, and tools, though never screen if this is true.

I kind of misunderstood that this was for the camera, my apologies. However, the camera is moveable with animations, it might require some extra scripting though and might be a little complicated.

there is something called the spring module. it is very useful for stuff like this, you should get it. its made by quenty, just make a module script in your replicated storage and reference it whenever you want to do stuff

How would I use springs for gun recoil? Could you please give an example?

here are some tutorials you can somehow put the code into your thing

This will not work, because my gun system goes off of user input, and not constantly doing it like Heartbeat.

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")

local player = Players.LocalPlayer

local mouse = player:GetMouse()
local camera = workspace.CurrentCamera

local Spring = require(game.ReplicatedStorage.SpringModule)
local RecoilSpring = Spring.new()

RecoilSpring:shove(Vector3.new(1, 0, 0))

game:GetService("RunService").Heartbeat:Connect(function(dt)
	local UpdatedRecoilSpring = RecoilSpring:update(dt)

	workspace.Camera.CFrame *= CFrame.Angles(math.rad(UpdatedRecoilSpring.X) * 2, 0, 0)	
end)

mouse.Button1Down:Connect(function()
	
end)

The problem is, I cannot get delta with UserInputService, and if I do input.Delta, sometimes it will be 0 (nan) for awhile, and everything breaks.

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
local Spring = require(game.ReplicatedStorage.SpringModule)

local player = Players.LocalPlayer
local mouse = player:GetMouse()
local camera = workspace.CurrentCamera
local RecoilSpring = Spring.new()


game:GetService("UserInputService").InputBegan:Connect(function(inputKey, GPE)
	if inputKey.UserInputType == Enum.UserInputType.MouseButton1 then 
		local dt = inputKey.Delta		
		RecoilSpring:shove(Vector3.new(.1, 0, 0))
		
		local updated = RecoilSpring:update(dt)
		

		camera.CFrame *= CFrame.Angles(math.rad(updated.X), 0, 0)
	end
	
end)

I don’t see how it is not compatible with yours though, in the tutorial it is based on the player’s input, according to here
image
where IsPlayerHoldingMouse variable changes depending on the input here
image

1 Like