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.
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,…)
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.
https://developer.roblox.com/en-us/api-reference/enum/MouseBehavior
https://developer.roblox.com/en-us/api-reference/class/InputObject
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.
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:
Download:
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 = TweenInfo.new(l,s,d)
return T:Create(o,i,t)
end
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 = CFrame.new(0,cameraY,0) * cameraOrientation
function updateCamera()
local pos = cam.CFrame.Position
cameraOrientation = CFrame.Angles(math.rad(cameraY/defaultCameraY*defaultCameraOrientation),0,0)
tween(cam,{CFrame=CFrame.new(pos.X,cameraY,pos.Z)*cameraOrientation},0.1):Play()
end
mouse.WheelForward:Connect(function()
cameraY = math.clamp(cameraY-zoomSpeed,heightRange.Min,heightRange.Max)
updateCamera()
end)
mouse.WheelBackward:Connect(function()
cameraY = math.clamp(cameraY+zoomSpeed,heightRange.Min,heightRange.Max)
updateCamera()
end)
mouse.Button1Down:Connect(function()
local up
local buttonUp
buttonUp = mouse.Button1Up:Connect(function()
buttonUp:Disconnect()
up = true
end)
repeat
local start = Vector2.new(mouse.X,mouse.Y)
RS.RenderStepped:Wait()
local current = Vector2.new(mouse.X,mouse.Y)
local pos = cam.CFrame.Position
if dynamicSpeed then
speed = cameraY/defaultCameraY*defaultSpeed
end
local offset = CFrame.new((start.X-current.X)*speed,0,(start.Y-current.Y)*speed)
local newCFrame = CFrame.new(pos.X,cameraY,pos.Z) * offset * cameraOrientation
tween(cam,{CFrame=newCFrame},0.1):Play()
RS.RenderStepped:Wait()
until up
end)
How would one also implement camera rotation with the rest?
I dont really hope, but if you can really answer i have a question: What if i want to swap one of movement sides with Y, how do i make it?
You’d basically just swap Y and Z. The Mouse X and Y would stay the same with the “current” variable, but you would change where it’s used with the “offset” variable. It uses the Mouse’s Y on the Z axis, but that could be moved to the Y axis instead and have Z be 0 instead of how it is with Y. But you’ll probably have to change a bit more if you want the scrolling feature to work properly as well. Just think about it logically step-by-step and you should be able to get it to work.