So I've made a few camera effects, one of them being a 'recoil' effect. It works by taking a few random "recoil-ish"(trademarked term) angles, creates a "target" angle, and then lerps the camera towards that angle. This is great and all, but I then need to figure out how much I need to move the camera back, to get back to its original point. I've tied it to renderStepped, so I need to count how many Frames its iterated, then put that against the remainder of a "Recoil Recover Time" I have. Here is the code, in full:


local Cam = game.Workspace.CurrentCamera
local RunService = game:GetService('RunService')
local UserInputService = game:GetService('UserInputService')

local Target=CFrame.Angles(0,0,0) -- TargetAngle
local TargRecover -- Reversed and reduction.

local Max = 3
local May = 3.5
local RecoilLength = .4 -- Time to get from A->B->A again. (A is start, B is Target, back to A is another lerp.)
local FiringRate = 1/12 -- "Bullets fired" per second.
local Start = 0
local Firing = false
local Frames = 0
local X = 0
local Y = 0
local Z = 0
local EX = 0
local EY = 0
local EZ = 0
local EXPLOSION = nil
local EXPL = CFrame.Angles(0,0,0)

--For every additional "Target", TargRecover must add and then subtract the new addition: this ensures it will always revert to the centre.

RunService:BindToRenderStep("cameraRenderUpdate", Enum.RenderPriority.Character.Value, function()
	if tick() - Start > FiringRate then --Checks if we CAN shoot.
		if Firing == true then --Checks if we ARE shooting
			Start = tick()
			print("Shoot A bullet")
			X = math.rad(math.random(May/4,May/1.2))
			Y = math.rad(math.random(-Max,Max))
			Z = math.rad(math.random(-Max,Max)/4)
			Target = CFrame.Angles(X,Y,Z)
			TargRecover = CFrame.Angles(-X,-Y,-Z)
		end
	else
		Frames = Frames+1
	end
	if tick()-Start<RecoilLength then
		if tick()-Start>RecoilLength/3 then
			Target = Target:lerp(TargRecover,((tick()-Start)/(RecoilLength))-.2)
			print((tick()-Start)/(RecoilLength))
		end
	elseif tick()-Start>RecoilLength then
			Target = CFrame.Angles(0,0,0)
	end
	if EXPLOSION ~= nil then
		local Force = (Cam.CoordinateFrame.p-EXPLOSION.Position).magnitude/3
		EX = EX-EX+math.rad(math.random(-5/Force,5/Force))
		EY = EY-EY+math.rad(math.random(-3/Force,3/Force))
		EZ = EZ-EZ+math.rad(math.random(-15/Force,15/Force))
		EXPL = CFrame.Angles(EX,EY,EZ)
		print(EXPL)
	else
		EX = EX-EX
		EY = EY-EY
		EZ = EZ-EZ
		EXPL = CFrame.Angles(EX,EY,EZ)
	end
	Cam.CoordinateFrame = Cam.CoordinateFrame:lerp(Cam.CoordinateFrame*Target,.3)*EXPL
	
end)




UserInputService.InputBegan:connect(function(mousecheck)
	if mousecheck.UserInputType == Enum.UserInputType.MouseButton1 then
		Firing = true
	end	
end)



UserInputService.InputEnded:connect(function(mousecheck)
	if mousecheck.UserInputType == Enum.UserInputType.MouseButton1 then
		Firing = false
	end	
end)

UserInputService.InputBegan:connect(function(mousecheck)
	if mousecheck.KeyCode == Enum.KeyCode.E then
		EXPLOSION = game.Workspace.Explosion
	end	
end)



UserInputService.InputEnded:connect(function(mousecheck)
	if mousecheck.KeyCode == Enum.KeyCode.E then
		EXPLOSION = nil
	end	
end)

But yeah... It will lerp back, towards the original point, but it will then overshoot. And with every additional recoil, its original point changes :/

I've tried to think of a method to make it re-trace its shooting steps, but I can't create a reliable method. Anyone got any thoughts?

tl;dr: Shoot once, moves camera away, moves camera back. PROBLEM 1: doesn't move camera back to original spot, moves it too far back. PROBLEM 20: Firing multiple shots changes the original spot, not from when you click.

(To use the explosion effect, just place a block in the workspace, call it Explosion, Hold down E and walk towards and away from it. EPILEPSY WARNING.)

1 comment

0