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 = Vector3.zero

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

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

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

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

local function updateCam(dt)
	cameraMovement(dt)
end

local connection

startCamera.Event:Connect(function(status, plot) 
	if status == true then 
		cam.CFrame = plot.Assets.Grid.CFrame * (CFrame.new(0, 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)
	else
		cam.CFrame = player.Character.HumanoidRootPart.CFrame
		cam.CameraSubject = player.Character.Humanoid
		cam.CameraType = Enum.CameraType.Custom
		
		connection:Disconnect()
		connection = nil
	end
end)

First I would replace

connection = run.RenderStepped:Connect(cameraMovement)

and

connection:Disconnect()
connection = nil

with

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

and

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 = Vector3.new(100, 0, 100)
local plotSize = Vector2.new(50, 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.

2 Likes

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