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
http://i.imgur.com/d3xziZe.png For visual aid.