How to establish a plane relative to player's screen and camera?

  1. What do you want to achieve?

I want players to be able to move their cameras with their mouse based on where it is on their screen.

  1. What is the issue?

I am unsure how I can orientate my plane.

  1. What solutions have you tried so far?

So far, I have managed to create a plane based on the player’s screen, but now I need to somehow orientate it so it matches with the orientation of my camera.

What I got so far:

What I want:

Code:

local cameraTargetPosition = HumanoidRootPart.Position
		local maxViewRange = 10
		
		local mousePositionScaleX = mouse.X / workspace.CurrentCamera.ViewportSize.X
		local mousePositionScaleY = mouse.Y / workspace.CurrentCamera.ViewportSize.Y
		
		if mousePositionScaleX > 0.5 then
			cameraTargetPosition += Vector3.new((mousePositionScaleX - 0.5) * 2 * maxViewRange, 0, 0)
		elseif mousePositionScaleX < 0.5 then
			cameraTargetPosition += Vector3.new((1 - mousePositionScaleX * 2) * -maxViewRange, 0, 0)
		end
		
		if mousePositionScaleY > 0.5 then
			cameraTargetPosition += Vector3.new(0, 0, (mousePositionScaleY - 0.5) * 2 * maxViewRange)
		elseif mousePositionScaleY < 0.5 then
			cameraTargetPosition += Vector3.new(0, 0, (1 - mousePositionScaleY * 2) * -maxViewRange)
		end

Feel free to improvise if you like :+1:

I’m confused. Do you want the camera to orient along the plane the player is seemingly interacting with, or do you want the plane to orient itself with the camera plane?

It’s a bit hard to explain with words, but imagine your screen being the plane for the camera to follow, hopefully, this side picture helps with what I want it it to be.

Right now, it’s rotated because I am using Vector which is relative to workspace

You will need to modify the camera’s Y position to be locked above the plane then.

local CameraPlaneOffset = 10 -- Change to modify the camera plane vertical offset, in studs.
game:GetService("RunService").RenderStepped:Connect(function(deltaTime)
    local Camera = workspace.CurrentCamera
    if (Camera) then
        local X, Y, Z = Camera.CFrame:ToEulerAnglesXYZ()
        Camera.CFrame = CFrame.new(Camera.CFrame.X, planePos.Y + CameraPlaneOffset, Camera.CFrame.Z) * CFrame.fromEulerAnglesXYZ(0, Y, Z)
    end
end)

Again, I really don’t know your target effect here. What I gave you is what I was able to interpret.

I guess another example of what I want to replicate is similar to the camera in League of Legends.

Oh, very well.

local PlaneSize = Vector3.zero -- Please change this to match the plane's Size at all times.
local PlaneCFrame = CFrame.new() -- Please change this to match the plane's CFrame at all times.

local BoundUnit = 2 -- The studs to bound unit conversion factor. Set to ideal value.
local CameraPlaneOffset = 10 -- Change to modify the camera plane vertical offset, in studs.
local CameraAngleOffset = 30 -- In degrees, change to set the constant X rotational value.
game:GetService("RunService").RenderStepped:Connect(function(deltaTime)
    local Camera = workspace.CurrentCamera
    if (Camera) then
        local _, Y, Z = Camera.CFrame:ToEulerAnglesXYZ()
        local Bounds = Vector3.new(PlaneSize.X, 0, PlaneSize.Z - math.tan(math.rad(CameraAngleOffset/(CameraPlaneOffset * BoundUnit))) * BoundUnit)
        Camera.CFrame = CFrame.new(math.clamp(Camera.CFrame.X, PlaneCFrame.X - Bounds.X/2, PlaneCFrame.X + Bounds.X/2), planePos.Y + CameraPlaneOffset, math.clamp(Camera.CFrame.Z, PlaneCFrame.Z - Bounds.Z/2, PlaneCFrame.Z + Bounds.Z/2)) * CFrame.fromEulerAnglesXYZ(math.rad(CameraAngleOffset), Y, Z)
    end
end)