How do you make a 2D Draggable camera?

How do i create a 2D Top down draggable camera like in Civilization 6?
Ive found this but its not exactly what im looking for.

1 Like

Can you describe the behavior you’re looking for in more detail? Or provide a video link or something?

i wanr a camera that behaves like the camera in City Skylines or Civilization 6 or any other 2D game (a top/side view, you can zoom in/out, move the cam around,…)

1 Like

Is it like a click and drag or does it move when the mouse reaches the edges of the screen, or both?

click and drag would be better

Something like this?

On click, set mouse behavior to LockCurrentPosition and connect a UIS.InputChanged event listener. This handles mouse movement by translating the camera depending on how much the mouse was moved. Since it’s locked, the InputObject.Delta property will hold the X and Y values representing mouse movement.

On mouse release, disconnect that event listener.

From the looks of that video, it doesn’t lock the mouse at all. But the idea is still the same. Just take the mouse’s current position and compare the difference with its last position and move the camera by that much.

1 Like

how would i do that/could you give me a code example?

Do you want scrolling zoom as well? I’ve decided just to code it anyway. If you do, do you want the panning speed to remain consistent regardless of the zoom distance?

it would be great if you can zoom in/out, panning speed should speed up when far out

Alright, I’m just working to polish things up now.

thank you for helping/coding this for me

Alright, it’s not perfect, but it’s something. I decided to put the default values as attributes to be edited more easily:


This is with DynamicSpeed enabled:

Overhead Drag Camera.rbxm (1.7 KB)

(Put in StarterCharacterScripts)

Code Preview:
local defaultSpeed = script:GetAttribute('Speed')
local defaultCameraY = script:GetAttribute('Height')
local defaultCameraOrientation = script:GetAttribute('Orientation')
local defaultZoomSpeed = script:GetAttribute('ZoomSpeed')
local heightRange = script:GetAttribute('HeightRange')
local dynamicSpeed = script:GetAttribute('DynamicSpeed')

local speed = defaultSpeed
local cameraY = math.clamp(defaultCameraY,heightRange.Min,heightRange.Max)
local cameraOrientation = CFrame.Angles(math.rad(defaultCameraOrientation),0,0)
local zoomSpeed = defaultZoomSpeed

local T = game:GetService('TweenService')
function tween(o,t,l,s,d)
	s = s or Enum.EasingStyle.Linear
	d = d or Enum.EasingDirection.InOut
	local i =,s,d)
	return T:Create(o,i,t)

local RS = game:GetService('RunService')
local Players = game:GetService('Players')
local player = Players.LocalPlayer
local mouse = player:GetMouse()
local cam = workspace.CurrentCamera
cam.CameraType = Enum.CameraType.Scriptable
cam.CFrame =,cameraY,0) * cameraOrientation

function updateCamera()
	local pos = cam.CFrame.Position
	cameraOrientation = CFrame.Angles(math.rad(cameraY/defaultCameraY*defaultCameraOrientation),0,0)

	cameraY = math.clamp(cameraY-zoomSpeed,heightRange.Min,heightRange.Max)

	cameraY = math.clamp(cameraY+zoomSpeed,heightRange.Min,heightRange.Max)

	local up
	local buttonUp
	buttonUp = mouse.Button1Up:Connect(function()
		up = true
		local start =,mouse.Y)
		local current =,mouse.Y)
		local pos = cam.CFrame.Position
		if dynamicSpeed then
			speed = cameraY/defaultCameraY*defaultSpeed
		local offset =*speed,0,(start.Y-current.Y)*speed)
		local newCFrame =,cameraY,pos.Z) * offset * cameraOrientation
	until up

How would one also implement camera rotation with the rest?