Need help understanding camera code

Hello recently I found this script in the toolbox and it works really good, but I don’t understand the code much. Can someone explain the code? Or help simplify the code. Also is this the best code? Is there an easier way or is there any bad practices in this code? Also how can I adjust the settings in the code? Any help is appreciated!

--by @mvyasu
--March 11 2023

--This script was made for LockFirstPerson
--You can turn this on by setting StarterPlayer.CameraMode to LockFirstPerson

--This will only work if this script is located here:
--StarterPlayer > StarterCharacterScripts

local FIRST_LAST_OFFSET = 2000

local Player = game.Players.LocalPlayer
local PlayerScripts = Player:WaitForChild("PlayerScripts", 10)
local PlayerModule = PlayerScripts and PlayerScripts:WaitForChild("PlayerModule", 10)
local CameraInput = PlayerModule and PlayerModule:FindFirstChild("CameraInput", true)

local getRotation = if CameraInput then require(CameraInput).getRotation else nil
local resetInputForFrameEnd = if CameraInput then require(CameraInput).resetInputForFrameEnd else nil

--this technique requires CameraInput underneath PlayerModule to get the camera input
--otherwise a lot of work would need to be done to replicate the camera input
--if CameraInput changes in the future, this could potentially break

if getRotation==nil then
	error("[SimpleCameraDelay]: PlayerModule.CameraModule.CameraInput or CameraInput.getRotation does not exist!")

local RunService = game:GetService("RunService")
local Camera = workspace.CurrentCamera

local Character = script.Parent.Parent
local Humanoid = Character:WaitForChild("Humanoid") :: Humanoid
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart") :: BasePart

local function lerp(currentValue: any, goalValue: any, alpha: number)
	return currentValue + (goalValue - currentValue) * alpha

local function getRotationInputVectorFromCFrame(cframe: CFrame)
	local _, _, priorCFrameRotZ = cframe:ToOrientation()
	local rotationWithoutZ = cframe * CFrame.Angles(0, 0, -priorCFrameRotZ)
	local priorCFrameRotX, priorCFrameRotY = rotationWithoutZ:ToOrientation()
	return, priorCFrameRotX)

--currentPosition (and currentRotation depending on what VerticalAngleConstraint is set to) can be insanely large numbers
--because they never loop around. Could this be a problem in the future?

local currentPosition = Camera.CFrame.Position
local currentRotation = getRotationInputVectorFromCFrame(Camera.CFrame)

local targetPosition = currentPosition
local targetRotation = currentRotation

local forceInstantFrameCount = 2

local lastRenderStepCFrame = Camera.CFrame
local cachedCameraInputRotation =
RunService:BindToRenderStep("CameraDelay_CompareLastRenderStepCFrame", Enum.RenderPriority.First.Value - FIRST_LAST_OFFSET, function()	
	do --handles setting the rotation input based from a scripted cframe
		local startCFrame = Camera.CFrame
		local wasCFrameScriptedBeforeFrame = startCFrame~=lastRenderStepCFrame
		if wasCFrameScriptedBeforeFrame and Camera.CameraType~=Enum.CameraType.Scriptable then
			local scriptedRotation = getRotationInputVectorFromCFrame(startCFrame)

			targetRotation = scriptedRotation
			currentRotation = targetRotation

			forceInstantFrameCount = 2
	--we need to steal the current rotation input from the CameraInput module found in the PlayerModule
	--but we need to do it before the CameraModule resets the input, at least for the mouse
	--that's why this needs to happen before the CameraModule changes the camera's CFrame
	do --handles camera input related stuff
		cachedCameraInputRotation = getRotation()

		--this will break zooming, but it eliminates the
		--camera's position jittering when the custom sensitivity is 0 for whatever reason
		local currentCameraSensitivity = script:GetAttribute("CameraSensitivity") or 1
		if resetInputForFrameEnd and Player.CameraMode==Enum.CameraMode.LockFirstPerson and currentCameraSensitivity==0 then
			--since this the case, this will only be done if the
			--player's CameraMode is locked to first person

RunService:BindToRenderStep("CameraDelay_AdjustCamera", Enum.RenderPriority.Camera.Value + 1, function(dt: number)
	if Camera.CameraType==Enum.CameraType.Scriptable then
		forceInstantFrameCount = 2
	local currentVerticalAngleConstraint = script:GetAttribute("VerticalAngleConstraint") or, 80)
	local currentCameraPositionDelay = script:GetAttribute("CameraPositionDelay") or 1
	local currentCameraRotationDelay = script:GetAttribute("CameraRotationDelay") or 1
	local currentCameraDelayScale = script:GetAttribute("CameraDelayScale") or 1
	local currentCameraSensitivity = script:GetAttribute("CameraSensitivity") or 1
	local deltaTimeUpscaled = dt * 60

	targetPosition = Camera.CFrame.Position
	targetRotation += -cachedCameraInputRotation * currentCameraSensitivity
	targetRotation =, math.clamp(targetRotation.Y, math.rad(currentVerticalAngleConstraint.Min), math.rad(currentVerticalAngleConstraint.Max)))
	local positionDelay = math.max(currentCameraPositionDelay * currentCameraDelayScale, 0)
	local rotationDelay = math.max(currentCameraRotationDelay * currentCameraDelayScale, 0)
	currentPosition = lerp(currentPosition, targetPosition, if positionDelay==0 then 1 else 0.1 * deltaTimeUpscaled * 1/positionDelay)
	currentRotation = lerp(currentRotation, targetRotation, if rotationDelay==0 then 1 else 0.1 * deltaTimeUpscaled * 1/rotationDelay)
	--for whatever reason, the CFrame for the camera doesn't seem to be set immediately
	--in certain circumstances.. so we need to do this for two frames instead of one
	if forceInstantFrameCount>0 then
		forceInstantFrameCount -= 1
		currentPosition = targetPosition
		currentRotation = targetRotation
	Camera.CFrame = * CFrame.Angles(0, currentRotation.X, 0) * CFrame.Angles(currentRotation.Y, 0, 0)

RunService:BindToRenderStep("CameraDelay_SetLastRenderStepCFrame", Enum.RenderPriority.Last.Value + FIRST_LAST_OFFSET, function()
	lastRenderStepCFrame = Camera.CFrame

Thank you.

Its really complicated, but Ill try,

Lerp is basically using the formula for Interpolation, which allows you to move an object to a specific object in a Linear way.

GetRotationVectorFromCFrame is getting the Rotation Values from the CFrame. By Default, the Rotations are untranslated, the function ToOrientation translates the Rotaton to Degrees, in a x, y, z order, and returns 3 values, which is why there is three variables.

From there is just getting, and applying values. Along with a statement checking if the camera is a specific type, and from there there are functions using math.max which can be used to get the max value of a set of numbers, while math.clamp, its used to limit the value between two numbers, it is then used to lerp the CFrame value under a specific time.

And below, the function is binded to RenderStepped

1 Like

Hello thanks for the explanation it was well written. But I have a question can I remove the if statements to check for player module? Also where can I adjust the settings I can’t tell where.

Edit: also what’s first last offset line 1


Since the Modules only return values once, you probably should, and as for the settingsz they should be inside the Modules, or at the top of the Script, it be stupid if they were applying just numbers instead of variable

Also first last offset is used for the Priority for the Bind, if the number is higher, it will run after something, but if its less, then it will run before something, which in the top of the script its 2000

1 Like

Didn’t notice this earlier thank you a lot!

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