Camera Recoil Going Behind Moving Player

I scripted a camera recoil system that is functional but if the player moves while shooting, the camera falls behind the player.

Video Example:

Code:

local Info = TweenInfo.new(0.1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out, 0, true)
local shakeTween = game.TweenService:Create(Camera, Info, {CFrame = Camera.CFrame * CFrame.Angles(math.rad(math.random(2, 5)), math.rad(math.random(-3, 3)), 0)})
shakeTween:Play()
1 Like

i think its prolly because when you made the tween the camera position you set stays the same so the tween will move you back to your previous position that is why when you stand still it wont go behind the player

so you should probably use a Lerp instead heres an example (i havent tested it yet)

local recoil = CFrame.new()

---- render stepped function im too lazy to tyype

recoil = recoil:Lerp(cframe stuff,0.2) -- the 0.2 is how smooth, the smaller it is, smoother

camera.CFrame *= recoil

This is whats going on now

This is the code I set it to:

local recoil = CFrame.new()
game["Run Service"].RenderStepped:Connect(function()
	recoil = recoil:Lerp(Camera.CFrame * CFrame.Angles(math.rad(math.random(2, 5)), math.rad(math.random(-3, 3)), 0), 0.2)
	Camera.CFrame *= recoil
end)

no, dont do that

for the lerp ONLY DO cframe angles

then after that make sure to set the recoil back to 0 in antoher function

for my recoil script I did:
note that this is from a FPS game, so you might need to tweak it a bit

vrecoil = 1.02
recoil = CFrame.new()

function fire()
    --fire stuff
task.wait(0.05)
    vrecoil = 0
end

-- rendersteped stuff
recoil = recoil:Lerp(CFrame.Angles(0,math.rad(vrecoil),0),0.2)
cam.CFrame *= recoil
3 Likes

This is good but it doesn’t have that same look that the old recoil did and it doesn’t reverse. How can I reverse it and why does it look a little different than before?

Old Look:

Code I put:

local recoil = CFrame.new()
		local oldCameraCFrame = Camera.CFrame
		local con; con = game["Run Service"].RenderStepped:Connect(function()
			recoil = recoil:Lerp(CFrame.Angles(math.rad(math.random(2, 5)), math.rad(math.random(-3, 3)), 0), 0.05)
			Camera.CFrame *= recoil
			task.spawn(function()
				task.wait(0.05)
				if (con) then
					recoil = recoil:Lerp(oldCameraCFrame, 0.1)
					con:Disconnect();
				end
			end)
		end)

Never mind it not looking the same, I got it fixed. How can I reverse it?

What’s the current code you’re using, please move while making the clips.

I understand you’ve switched between multiple codes,
We didn’t get to know if the less cooler Lerp code you were
given worked while moving player position.

If it did, and was a lerp code, please provide it and I’ll try to replicate it more to what it looked like with your old Tween.

TweenService is not suitable for tasks like these, as it will go through the start and end values while you’re moving, which causes the camera to go behind during recoil. I highly recommend using springs for this, as they can adapt to constantly changing values while applying some kind of force. I would recommend checking out a first person shooter tutorial. For example:

Here is also my example to get you started:

local recoilSpring = Spring.new({
    Damper = 1,
    Speed = 10
})

-- To be called whenever a gun is fired
local function shoot()
    recoilSpring:Impulse(Vector3.new(-3, 0, 0))
end

-- To be called every frame
local function update(dt: number) -- dt: delta time
    local recoil = recoilSpring:Update(dt)
    camera.CFrame *= CFrame.Angles(recoil.X, recoil.Y, recoil.Z)
end

For a spring module, I can recommend Spring module from NevermoreEngine by @Quenty.

1 Like

This is the code I’m using right now

local recoil = CFrame.new()
		local oldCameraCFrame = Camera.CFrame
		local con; con = game["Run Service"].RenderStepped:Connect(function()
			recoil = recoil:Lerp(CFrame.Angles(math.rad(math.random(2, 5)), math.rad(math.random(-3, 3)), 0), 0.05)
			Camera.CFrame *= recoil
			task.spawn(function()
				task.wait(0.05)
				if (con) then
					recoil = recoil:Lerp(oldCameraCFrame, 0.1)
					con:Disconnect();
				end
			end)
		end)

you can just make it negative values when lerping

here’s the newest code but it doesn’t fully reverse. what can I do to make it fully reverse?

local recoil = CFrame.new()
		local oldCameraCFrame = Camera.CFrame
		local con; con = game["Run Service"].RenderStepped:Connect(function()
			local randomX = math.random(2, 5)
			local randomY = ((math.random(1, 2) == 1) and 5) or -5
			recoil = recoil:Lerp(CFrame.Angles(math.rad(randomX), math.rad(randomY), 0), 0.05)
			Camera.CFrame *= recoil
			task.spawn(function()
				task.wait(0.1)
				recoil = recoil:Lerp(CFrame.Angles(math.rad(-randomX), math.rad(-randomY), math.rad(-1)), 0.05)
				Camera.CFrame *= recoil
				task.wait(0.01)
				if (con) then
					con:Disconnect();
				end
			end)
		end)

what do you mean? send a video please

After shooting, the camera will go back up a little bit but not all the way to the original CFrame

turn up the values ig
whatever you multiplied you just divide it?

Could you give me an example on how I would do that?

for example if you did like * 1.01 you would then / 1.01

What would I divide? Take a look at the most recent code I sent

in some code (after you fire) wait like 0.05 seconds and then do it

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