One way to create a recoil system is to use a script that changes the player’s camera angle when the gun is fired. To do this, you could adjust the CFrame (coordinate frame) of the player’s camera based on the direction of the shot and a random offset to create the effect of recoil.
Here is an example implementation:
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local camera = workspace.CurrentCamera
local gun = script.Parent
local function onFire()
-- Get the direction of the shot
local target = mouse.Hit.p
local origin = gun.Position
local direction = (target - origin).unit
-- Calculate a random offset for the recoil
local randomX = math.random(-5, 5)
local randomZ = math.random(-5, 5)
-- Adjust the CFrame of the camera based on the direction and offset
local newCFrame = camera.CFrame * CFrame.new(0, 0, -1) * CFrame.Angles(math.rad(randomX), 0, math.rad(randomZ))
-- Apply the new CFrame to the camera
camera.CFrame = newCFrame
end
-- Connect the onFire function to the gun's "Fire" event
gun.Fire.Event:Connect(onFire)
This is just one example, and you can adjust the values and logic to get the desired effect for your game.
Yeah it would be a local script, I personally use something very similar with the only big difference being that I tween the CFrame to prevent the recoil from feeling too jumpy.
local cam = workspace.CurrentCamera
local TS = game:GetService("TweenService")
local tweenInfo = TweenInfo.new(0.025,Enum.EasingStyle.Elastic,Enum.EasingDirection.InOut,0,false,0)
local function recoil()
-- Randomize our horizontal recoil adjust these numbers to your liking.
local randY = math.random(-7,7)
local randZ = math.random(-7,7)
local oldCFrame = cam.CFrame -- Useful if you want the gun to go back to the original position after some time.
local tweenProperties = {CFrame = cam.CFrame * CFrame.Angles(0.08,math.rad(randY), math.rad(randZ))} -- Setup our tweens properties
local recoilTween = TS:Create(cam,tweenInfo,tweenProperties)
recoilTween:Play() -- Play the tween!
end
I would recommend running the recoil in a coroutine especially if you decide to lerp it instead of tweening it.
local recoilCoro = coroutine.create(recoil)
coroutine.resume(recoilCoro)
There’s an issue with tween, it is “stationary”.
If you move during the recoil animation camera glitches out because it stays in place during the animation.
local raise = 0.05 --Whatever you want
local randY = math.random(min,max)
local randZ = math.random(min,max)
for i = 0,1,.5 do
task.wait()
cam.CFrame = cam.CFrame:Lerp(cam.CFrame * CFrame.Angles(math.rad(raise),math.rad(randY),math.rad(randZ)),0.2)
end