Top-down camera not working correctly

  1. What do you want to achieve? Keep it simple and clear!

I want to make a top-down camera controllable by the player’s mouse, that you can click and drag to move around.

  1. What is the issue? Include screenshots / videos if possible!

The core system works, which is clicking and dragging, but the camera randomly stops facing down once you click and it also resets the camera’s position whenever you click again.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I have attempted to find tutorials on this, but there is a big lack of tutorials in the field of top-down camera systems like I want to achieve.

Here is the code:

local plr = game.Players.LocalPlayer
local char = game.Workspace:FindFirstChild(plr.Name)
local PlayerModule = require(game.Players.LocalPlayer.PlayerScripts:WaitForChild("PlayerModule"))
local Controls = PlayerModule:GetControls()
Controls:Disable()
local Cam = game.Workspace.CurrentCamera
local camPlace = game.Workspace.CamPlace
Cam.CameraType = "Scriptable"
Cam.CFrame = game.Workspace.CamPlace.CFrame
local mouse = plr:GetMouse()
local moving = false
local dragSpeed = 1.1

function getMouseTarget()
	local cursorPosition = game:GetService("UserInputService"):GetMouseLocation()
	local oray = game.workspace.CurrentCamera:ViewportPointToRay(cursorPosition.x, cursorPosition.y, 0)
	return oray
end

-- Zoom
mouse.WheelForward:Connect(function()
	Cam.CFrame = Cam.CFrame + (Cam.CFrame.ZVector * -3)
end)

mouse.WheelBackward:Connect(function()
Cam.CFrame = Cam.CFrame + (Cam.CFrame.ZVector * 3)
end)

local dragOrigin

UserInputService.InputBegan:Connect(function(input, gameProcessed)
	
	if input.UserInputType == Enum.UserInputType.MouseButton3 then
		dragOrigin = game:GetService("UserInputService"):GetMouseLocation()
		moving = true
		
		repeat game["Run Service"].Heartbeat:Wait()
			local CPos = game:GetService("UserInputService"):GetMouseLocation()
			local difference = CPos-dragOrigin
			print(difference.X, difference.Y, difference.X * dragSpeed, difference.Y * dragSpeed)
			Cam.CFrame = CFrame.new(difference.X * dragSpeed, Cam.CFrame.Y, difference.Y * dragSpeed)
		until moving == false
	end
end)

UserInputService.InputEnded:Connect(function(input, gameProcessed)
	if input.UserInputType == Enum.UserInputType.MouseButton3 then
		moving = false
	end
end)

Here is a video showcasing the issue:

Try this simpler and easier script that I think will work

local cam = workspace.CurrentCamera
 
local char = script.Parent
local hrp = char:WaitForChild("HumanoidRootPart") 
 
 
cam.CameraType = Enum.CameraType.Scriptable
 
 
local cameraPart = Instance.new("Part")
cameraPart.Transparency = 1
cameraPart.CanCollide = false -- You can either make it jump throughtable or not
cameraPart.Parent = workspace
 
cameraPart.CFrame = CFrame.new(hrp.Position + Vector3.new(0, 20, 0), hrp.Position) -- The posotion of where you want it to face
 
 
local bp = Instance.new("BodyPosition")
bp.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
bp.Parent = cameraPart -- If your part is not cameraPart just rename it
 
 
game:GetService("RunService").RenderStepped:Connect(function()
    
    bp.Position = hrp.Position + Vector3.new(0, 20, 0)
    
    cam.CFrame = cameraPart.CFrame
end)

The rotation is reset because you aren’t setting any rotation when setting the camera’s CFrame. You need to set some rotation using CFrame.Angles().

Cam.CFrame = CFrame.new(difference.X * dragSpeed, Cam.CFrame.Y, difference.Y * dragSpeed)
* CFrame.Angles(Cam.Rotation.X, Cam.Rotation.Y, Cam.Rotation.Z)

And the position is resetting every time you start dragging again because you aren’t considering where the camera is when you start dragging when setting a new position. You set the position to the “difference” position, but you should set it to the camera’s position + the difference position.
Instead of for example difference.X * dragSpeed you should probably do something like this difference.X * dragSpeed + originalCameraPos. You would set the originalCameraPos before the repeat loop.

1 Like