Need help with Camera System!

Hello, Robloxians!

I’m trying to make a camera system where you can use WASD to move the camera and use your scroll wheel to zoom in/out while also not being able to see the player. I had gotten the code from a post and modified it a tiny bit.

Here is a video of what I have so far:

I would like to improve the controls and add zooming(the code I put in doesn’t zoom)
If i press WASD, it goes in the direction I want, but diagonally.

Is there anyway to make it have the same isometric or orthographic(idk) camera angle while also having these controls?

here is my current code in StarterPlayerScripts:


local RS = game:GetService("RunService")
local UIS = game:GetService("UserInputService")

local default_plot = workspace.Plots.PlotDefault

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

local CAMERA_MOVE_SPEED_MAX = 15
local CAMERA_MOVE_FORCE = 100
local cameraVelocity = Vector3.zero

local SCROLL_DIST = 15
local SCROLL_MIN_DIST = 10
local SCROLL_MAX_DIST = 23

function getCameraMoveDirInput(): Vector3
	local dir = Vector3.zero
	
	if UIS:IsKeyDown(Enum.KeyCode.W) then dir += Vector3.xAxis end
	if UIS:IsKeyDown(Enum.KeyCode.A) then dir -= Vector3.zAxis end
	if UIS:IsKeyDown(Enum.KeyCode.S) then dir -= Vector3.xAxis end
	if UIS:IsKeyDown(Enum.KeyCode.D) then dir += Vector3.zAxis end
	
	if dir ~= Vector3.zero then
		dir = dir.Unit
	end

	return dir	
end

function clampV3Magnitude(v: Vector3, min: number, max:number): Vector3
	return v.Unit * math.clamp(v.Magnitude, min,  max)
end

function updateCameraMovement(dt)
	local accelDir = getCameraMoveDirInput()
	--local accelDir = (camera.CFrame:VectorToWorldSpace(getCameraMoveDirInput()) * Vector3.yAxis).Unit

	if accelDir ~= Vector3.zero then
		cameraVelocity += CAMERA_MOVE_FORCE * accelDir * dt
		cameraVelocity = clampV3Magnitude(cameraVelocity, 0, CAMERA_MOVE_SPEED_MAX)
	else
		cameraVelocity *= math.clamp(1 - (15 * dt), 0, 1)
	end
	
	mouse.WheelForward:Connect(function()
		if SCROLL_DIST <= SCROLL_MAX_DIST then
			SCROLL_DIST += 1
		end
	end)

	mouse.WheelBackward:Connect(function()
		if SCROLL_DIST >= SCROLL_MIN_DIST then
			SCROLL_DIST -= 1
		end
	end)

	camera.CFrame += cameraVelocity * dt * SCROLL_DIST

end

function updateCamera(dt)
	updateCameraMovement(dt)
end

camera.CFrame = CFrame.new(default_plot.Position.X, 500, default_plot.Position.Z) * CFrame.Angles(0, math.rad(-45), 0) * CFrame.Angles(-math.rad(45), 0, 0)

camera.FieldOfView = script:GetAttribute('FOV')

camera.CameraType = Enum.CameraType.Scriptable
camera:GetPropertyChangedSignal("CameraType"):Connect(function()
	camera.CameraType = Enum.CameraType.Scriptable
end)

RS.RenderStepped:Connect(updateCamera)

Thank you.

2 Likes

I presume you probably haven’t noticed this, but according to your code you’ve done exactly what you’ve told it to do - move relative to the Vector3 axis. Now your camera is currently at a diagonal to the baseplate below. As such your camera is moving properly - just you haven’t considered the rotation.

I think your fix would therefore be to do some pythagoras and resolve the direction through a combination of both the xAxis and zAxis. You can either hard code these values or do it relative to your camera.

The general principle should be:
1 = zAxis^2 + xAxis^2
→ Which would therefore tell you that the value you should use (for a 45 degree angle) should be 1 = 2a^2
–>0.5 = a^2
→ 0.5^(0.5) = a
So you’d be adjusting by a in both angles, and depending on the combination of the values (both positive and negative) you should be able to move evenly in all plains.

1 Like

How would I apply this formula to my code? Would I create a method that uses pythagoràs like this?

function pythagoras(x: number, y: number) : () -- Utilizzar il 'Teorema di Pitagora (radice a^2 + b^2 = c, oppure a^2 + b^2 = c^2 
    return math.sqrt(x^2, y^2)
end

Thank you for the help btw :grin:

1 Like

Well it really depends on what method you want to apply to it.

If your camera angle is unchanging, then you can obviously just use fixed numbers.

However:

  • You’ve rotated the camera somehow, either by a specific angle or using the combination of a Vector to adjust it. As such you know how to get from A → B in this situation.
  • Although I can’t quote the mathematics off my head, you should:
    – Using SOHCAHTOA, work out the angle of the camera → this is important as we need to know, based on the angle, how much to adjust by.
    – Again, using SOHCAHTOA, seeming as we know we have a fixed unit of “1” during every vector movement. We can then infer that, for example using sine and a 60 degree camera angle → sin(60) * 1 = amount to adjust by.
    – This number will then be the amount to adjust by for that specific direction. You’d then have to do it once more, using one of the other two methods (cosine in this situation as it mitigates error) to work out the other amount you need to adjust by.

In mathematics this is called the “Pythagorean Identity”:
sin²θ+cos²θ = 1

1 Like