Camera Animation Module

Hey. I’ve made a module to create camera cutscenes easily and want to improve the resource usage, and execution time on the module.

I’ve seen many posts talking about what to do and not to do (Use functions for repeating code, don’t use elseif, and use BindToRenderStep instead of RunService.RenderStepped).

I’ve looked at the memory usage of the module and done speed tests on the MoveCamera function of the code.

After testing, I found that the code below had the most consistent time (~0.00001) while the others did not (~0.00001 or ~0.00002) and that the code below had the lowest memory usage (0.007 MB) over the others (0.008 MB, occasionally 0.007 MB when putting the math to find the bezier curve into a function, and 0.011 when putting the individual pieces of code to set the camera position into functions which were in a table and keeping the math to find the bezier curve in a function).

All the methods mentioned above have been considered. It seems that using “bad” coding practices have been better resource and execution time-wise. So what’s the deal and how can I improve my code?


local module = {}
local p0, p1, p2, p3, focusingType, focusPoint
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local Elapsed = script:WaitForChild("Elapsed")
local Camera = workspace.CurrentCamera
local CurrentTween

local function MoveCamera()
	local t = Elapsed.Value
	local tu = math.min(t + 0.0001)
	local tc = os.clock()
	if p3 then
		if focusingType == "FollowTrack" then
			Camera.CFrame = CFrame.new((1 - t)^3*p0 + 3*(1 - t)^2*t*p1 + 3*(1 - t)*t^2*p2 + t^3*p3, (1 - tu)^3*p0 + 3*(1 - tu)^2*tu*p1 + 3*(1 - tu)*tu^2*p2 + tu^3*p3)
		elseif focusingType == "FollowPoint" then
			Camera.CFrame = CFrame.new((1 - t)^3*p0 + 3*(1 - t)^2*t*p1 + 3*(1 - t)*t^2*p2 + t^3*p3, focusPoint)
		else
			Camera.CFrame = CFrame.new((1 - t)^3*p0 + 3*(1 - t)^2*t*p1 + 3*(1 - t)*t^2*p2 + t^3*p3)
		end
	elseif p2 then
		if focusingType == "FollowTrack" then
			Camera.CFrame = CFrame.new((1 - t)^2 * p0 + 2 * (1 - t) * t * p1 + t^2 * p2, (1 - tu)^2 * p0 + 2 * (1 - tu) * tu * p1 + tu^2 * p2)
		elseif focusingType == "FollowPoint" then
			Camera.CFrame = CFrame.new((1 - t)^2 * p0 + 2 * (1 - t) * t * p1 + t^2 * p2, focusPoint)
		else
			Camera.CFrame = CFrame.new((1 - t)^2 * p0 + 2 * (1 - t) * t * p1 + t^2 * p2)
		end
	elseif p1 then

		if focusingType == "FollowTrack" then
			Camera.CFrame = CFrame.new(p0:Lerp(p1, t), p1)
		elseif focusingType == "FollowPoint" then
			Camera.CFrame = CFrame.new(p0:Lerp(p1, t), focusPoint)
		else
			Camera.CFrame = CFrame.new(p0:Lerp(p1, t))
		end
	end
	print(os.clock() - tc)
end

local function interpolate(desc)
	if CurrentTween then
		CurrentTween:Pause()
		CurrentTween:Destroy()
		CurrentTween = nil
	end

	Elapsed.Value = 0
	CurrentTween = TweenService:Create(Elapsed, desc, {Value = 1})
	CurrentTween:Play()
	Camera.CameraType = Enum.CameraType.Scriptable
	RunService:BindToRenderStep("Camera_Move", 10, MoveCamera)
	CurrentTween.Completed:Wait()
	RunService:UnbindFromRenderStep("Camera_Move", 10, MoveCamera)
	Camera.CameraType = Enum.CameraType.Custom
	CurrentTween:Destroy()
	CurrentTween = nil
	p0, p1, p2, p3 = nil, nil, nil, nil
end

function module:QuadBezierCameraInterpolation(start:Vector3,curvePoint1:Vector3,finish:Vector3,desc:TweenInfo,movment:string,lookingPoint:Vector3)
	p0, p1 ,p2, p3, focusingType, focusPoint = start, curvePoint1, finish, nil, movment, lookingPoint
	interpolate(desc)
end
function module:CubicBezierCameraInterpolation(start:Vector3,curvePoint1:Vector3,curvePoint2:Vector3,finish:Vector3,desc:TweenInfo,movment:string,lookingPoint:Vector3)
	p0, p1 ,p2, p3, focusingType, focusPoint = start, curvePoint1, curvePoint2, finish, movment, lookingPoint
	interpolate(desc)
end
function module:LinearCameraInterpolation(start:Vector3,finish:Vector3,desc:TweenInfo,movment:string,lookingPoint:Vector3)
	p0, p1 ,p2, p3, focusingType, focusPoint = start, finish, nil, nil, movment, lookingPoint
	interpolate(desc)
end

return module