How to add boundaries to a freemove camera script I have?

Hello. I have a camera freemove script, that allows you to move around with the camera with the keys WASD, and I was wondering how to add boundaries to it. The camera is used inside a building function to be able to easily build on your plot, and I don’t want the player to be able to pan their camera anywhere in the world. I am not very good at camera manipulation so I’m pretty much lost when it comes to adding a boundary system (one that doesn’t jitter the camera back and forth once you reach the edges). ANybody got any ideas?

Heres my camera freemove script

local run = game:GetService("RunService") 
local uis = game:GetService("UserInputService")

repeat wait() until workspace.CurrentCamera

local cam = game.Workspace.CurrentCamera
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()

local movementSpeed = 80
local moveForce = 900

local velocity =

local startCamera = game.ReplicatedStorage.Remotes:WaitForChild("Camera")

local function inputs()
	local direction =
	if uis:IsKeyDown(Enum.KeyCode.A) then
		direction += Vector3.xAxis
	if uis:IsKeyDown(Enum.KeyCode.D) then
		direction -= Vector3.xAxis
	if uis:IsKeyDown(Enum.KeyCode.W) then
		direction += Vector3.zAxis
	if uis:IsKeyDown(Enum.KeyCode.S) then
		direction -= Vector3.zAxis
	if direction ~= then
		direction = direction.Unit
	return direction

local function clamp(v, min, max)
	return v.Unit * math.clamp(v.Magnitude, min, max)

local function cameraMovement(dt)
	local direction = inputs()
	if direction ~= then
		velocity += moveForce * direction * dt
		velocity = clamp(velocity, 0, movementSpeed)
		velocity *= math.clamp(1 - (15 * dt), 0, 1_)
	cam.CFrame += velocity * dt

local function updateCam(dt)

local connection

startCamera.Event:Connect(function(status, plot) 
	if status == true then 
		cam.CFrame = plot.Assets.Grid.CFrame * (, 90, 0) * CFrame.Angles(math.rad(45), -math.rad(180), 0))
		cam.CameraSubject = plot.Assets.Grid
		cam.CameraType = Enum.CameraType.Scriptable
		connection = run.RenderStepped:Connect(cameraMovement)
		cam.CFrame = player.Character.HumanoidRootPart.CFrame
		cam.CameraSubject = player.Character.Humanoid
		cam.CameraType = Enum.CameraType.Custom
		connection = nil

First I would replace

connection = run.RenderStepped:Connect(cameraMovement)


connection = nil


run:BindToRenderStep("cameraMovement", Enum.RenderPriority.Camera.Value + 1, cameraMovement)`


local s, e = pcall(function() run:UnbindFromRenderStep("cameraMovement") end)
if (s) warn(e) end

respectively. That will ensure your camera movement stuff always happens after roblox does any of theirs. Might not strictly be necessary but it’s good practice.

Then you just need to clamp the location. How exactly you define a boundary is up to you. Let’s say you have a center position and a Vector2 size:

local plotCenter =, 0, 100)
local plotSize =, 50)

Then where you have cam.CFrame += velocity * dt, replace that line with something like

local cf = cam.CFrame + velocity * dt
local x, z = plotCenter.X, plotCenter.Z
local w, h = plotSize.X, plotSize.Y
cf.X = math.clamp(cf.X, x - w / 2, x + w / 2)
cf.Z = math.clamp(cf.Z, z - h / 2, z + h / 2)
cam.CFrame = cf

i.e. clamp the X and Z positions of the camera to be in your box.

1 Like

Quick question, what do you mean by this?

Or more specifically, what is the Vector2 size used for, and how do i get it? Is the X the length of the plot size, and the Y is the height, or is it something different?

Edit: Nvm I figured it out, its all working perfectly. Thank you mate, it means a lot :slight_smile:

1 Like