How To Set Camera Zoom Distance

I am trying to set the camera zoom distance of players via script. In doing so, I am not referring to CameraMaxZoomDistance or CameraMinZoomDistance. I want to keep the min and max range the same, while just adjusting the current zoom value. How can I accomplish this?

A simple fix would be a LocalScript inside StarterPlayerScripts with the following statement:

workspace.CurrentCamera.FieldOfView = ...

Increasing the FOV will make the camera zoom out.
Decreasing will make the camera zoom in.

As for a CFrame-based approach I came up with some math,

--// SERVICES //--
local RS = game:GetService("RunService")

--// PLAYER //--
local plr = game.Players.LocalPlayer

--// CAMERA //--
local cam = workspace.CurrentCamera

--// VALUES //--
local isZoomLocked = false
local distance = 50

--//--//--//--//--//--//--//--//--//--//--//--//--

local function SetDistanceFromCamera()
	local focusDistance = (cam.CFrame.Position - cam.Focus.Position).Magnitude

	cam.CFrame = CFrame.new(
		cam.CFrame.Position + (cam.CFrame.LookVector * (focusDistance - distance)),
		cam.Focus.Position + (cam.CFrame.LookVector * (focusDistance - distance))
	)
end

local function SetZoomLocked(state)
	if state and not isZoomLocked then
		isZoomLocked = true --// RunService doesn't have a built in way to check if something is already bound.
		plr.CameraMinZoomDistance = 1 --// Prevent LocalTransparencyModifier.
		RS:BindToRenderStep("LockDistance", Enum.RenderPriority.Camera.Value + 1, function()	
			SetDistanceFromCamera()
		end)
	elseif not state and isZoomLocked then
		isZoomLocked = false
		plr.CameraMinZoomDistance = 0.5
		RS:UnbindFromRenderStep("LockDistance")
	end
end

SetZoomLocked(true)

I did some googling into your topic to see if someone else had already found a solution but I was surprised to find nothing. So I’ve decided to make this code open source.

Here is the grabbable LocalScript:
https://create.roblox.com/marketplace/asset/13465183741/LockCameraDistance

Now, what is this script doing?

Well, we are binding a function that runs right before the camera is updated each frame. Inside this function, we get the focus distance between the camera’s position and it’s current focus (the player). This distance IS the default zoom value that you find in Roblox.

As for the CFrame math:
We use a CFrame:LookAt() approach where the origin of the camera is:

cam.CFrame.Position + (cam.CFrame.LookVector * (focusDistance - distance))

The origin takes the normal camera position then adds on the .LookVector multiplied by our adjusted zoom. .LookVector is like a line in space, when we multiply it by a number we go up and down the line; which we call its magnitude in mathematics.

And the position we make the camera look at is:

cam.Focus.Position + (cam.CFrame.LookVector * (focusDistance - distance))

This is exactly the same, but instead, we use the focus to make sure the camera is rotated in the correct direction!

Notes:

  • Distance can be any positive value. Negatives were not tested and probably will cause funky behavior.
  • Use SetZoomLocked(true or false) to turn the zoom lock off and on!
  • This script is only 34 lines in length. You will probably need to modify it to meet your specific needs but the math should hold true.
  • I included plr.CameraMinZoomDistance because the player is still able to use the scroll wheel to theoretically zoom which causes the player to go first person if the scroll too much.

I hope this helps! :slight_smile:

2 Likes

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