Recoil system for guns

Hello. Recently I’ve been having fun with making guns in Roblox Studio. However I can’t think of a way to make a working (smooth) recoil system.

At first I made a working recoil system. Everytime I shoot I multiplied the Camera CFrame by Cframe.Angles, which would look like this.

Camera.CFrame *= CFrame.Angles(math.rad(3), 0, 0)

This gave me a choppy recoil, though, so then I tried TweenService. That didn’t work either, because when I move the camera doesn’t follow my character.

Tried Lerping the camera too, but since I fire my shots in a ‘RenderStepped’ event, the code below the function does not run, leaving me with no debounce and no way to have a cooldown.

RS.Stepped:Connect(function(dt)
	if UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) and not debounce then
		local MousePos = Mouse.Hit.Position
		Event:FireServer(MousePos, Camera.CFrame.Position)
		

		lerp()
		
		debounce = true
		wait(waitTime)
		debounce = false
	end
end)

This is my lerp function:

function lerp()
	local Goal = Camera.CFrame * CFrame.Angles(math.rad(3), 0, 0)
	for increment = 0, 1, .01 do
		wait()
		Camera.CFrame:Lerp(Goal, increment)
	end
end

I also read about Spring Modules, but that’s wayyy too complicated for my scripting knowledge( unless you just give me the code :wink: , jk)

So, do you guys have any other ideas for making a Smooth Recoil System? If so, please help me out.

3 Likes

They’re actually quite straightforward. Read this topic for more information:

Not sure if this is what you’re looking for, or if its the quality you want but it worked for me, keep in mind it will yield the code

Function:

local function recoilFunction(intensity, increment, time)
	for i = 0, time, increment do
		local goal = camera.CFrame * CFrame.Angles(math.rad(intensity), 0, 0)
		local newCF = camera.CFrame:Lerp(goal, i)
		camera.CFrame = newCF
		game["Run Service"].RenderStepped:Wait()
	end
end

intensity is really how many degrees it will rotate
increment is well, the increment, best at 0.1 (imo)
time is how long it will take, but your increment can change this if it isnt 0.1

Full code I used (you could just use your own with this function):

local player = game:GetService("Players").LocalPlayer
local inputService = game:GetService("UserInputService")

local camera = workspace.CurrentCamera
local debounce = nil

local function recoilFunction(intensity, increment, time)
	for i = 0, time, increment do
		local goal = camera.CFrame * CFrame.Angles(math.rad(intensity), 0, 0)
		local newCF = camera.CFrame:Lerp(goal, i)
		camera.CFrame = newCF
		game["Run Service"].RenderStepped:Wait()
	end
end

inputService.InputBegan:Connect(function(input, gp)
	if gp then return end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		if debounce and os.clock() - debounce < 2 then return end
		debounce = os.clock()
		recoilFunction(10, 0.1, 0.5)
	end
end)

Hope this helps

5 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.