I’m trying to create accurate recoil in my game, and I’m doing this by using methods by triple A titles such as Apex Legends or Battlefield V.
Recoil in Apex Legends (Focus on camera):
Recoil in Battlefield V(Focus on camera):
I will be using the following variables to explain each scenario (Assume numbers in degrees):
Start angle = S
End angle = E
Camera movement on the Y axis = Y
Recoil Applied = R
Recoil to Counter = C
RITSS = Recoil Increases Till Stop Shooting
Scenario one: RITTS and camera is not moved, it returns to normal.
S = 0, E = 0, Y = 0, R = 30, C = 30
Scenario two: RITSS and camera is slightly countering recoil, returns to normal.
S = 0, E = 0, Y = -15, R = 30, C = 15
Scenario three: RITTS and camera completely counters recoil, camera remains level.
S = 0, E = 0, Y = -30, R = 30, C = 0
Scenario four: RITTS and camera overcompensates for recoil, camera remains level.
S = 0, E = -15, Y = -45, R = 30, C = 0
Scenario five: RITTS and camera gets moved up with recoil, camera returns to level + amount moved.
S = 0, E = 15, Y = 15, R = 30, C = 30
So far, I have managed to make it so the recoil keeps increasing until they stop shooting, and then return to the angle they were aiming it if they didn’t move the camera.
However, if they did keep the camera level for example, where you would expect the camera to remain level the camera still moves the camera down by how much recoil there is.
Also, the minimum angle when shooting is reduced by how much recoil there is, for example if the minimum angle is -85, and there is recoil of 15 the minimum angle is -70 while shooting then returns to -85 after shooting.
This is just the bare bones of what I have at the moment since in the framework I have this is spread over hundreds of lines.
My recoil:
local cf = CFrame.new
local ang = CFrame.Angles
local rad = math.rad
local v3 = Vector3.new
local camera = workspace.CurrentCamera
camera.CameraType = Enum.CameraType.Scriptable
local player = game:GetService("Players").LocalPlayer
local chr = player.Character
local rootpart = chr.HumanoidRootPart
player.CameraMode = Enum.CameraMode.LockFirstPerson
local DeltaY = 0
local RotY = 0
local shooting = false
local rpm = 60/1200
local lastshot = 0
local vcam = 0
local vccf = cf()
player:GetMouse().Button1Down:Connect(function()
shooting = true
end)
player:GetMouse().Button1Up:Connect(function()
shooting = false
end)
local function firestep()
if shooting then
local tfl = tick() - lastshot
if tfl >= rpm then
vcam = vcam + rad(2)
lastshot = tick()
print("shooting")
end
end
vccf = vccf:lerp(ang(vcam, 0, 0), 0.1)
if tick() - lastshot > rpm*1.2 then--or not shooting then
if vcam > 0.001 then
vcam = vcam/2
print("div")
else
vcam = 0
end
end
end
game:GetService("UserInputService").InputChanged:Connect(function(input, gpe)
if gpe then return end
if input.Delta ~= v3() then
DeltaY = input.Delta.Y*0.2
end
end)
game:GetService("RunService").RenderStepped:Connect(function(s)
firestep()
RotY = math.min(math.max(RotY - rad(DeltaY), rad(-85)), rad(85))
camera.CFrame =
cf(rootpart.Position)*
cf(0, 1.8, 0)*
ang(RotY,0,0)*
vccf
DeltaY = 0
end)
You can try this out for yourself by putting a local script in an empty game in StarterCharacterScripts.
My recoil:
I really need help on this, I tried creating a counter lerp or taking away DeltaY from the recoil but it doesn’t work and I’m really stuck for ideas. I would really appreciate it if someone could help me!