-
What do you want to achieve?
I have a topdown RPG game where 35% of the screen is taken up by a user interface (either horizontally, or vertically, which depends on screen size). To make the game not feel bizarre and cumbersome to control, I have devised a method of offsetting the camera by the amount of screen space taken by the UI, essentially mimicking a sort of split-screen effect. -
What is the issue?
I can’t seem to find a good enough method of detecting screen size in 3D space, allowing me to calculate the missing area in world space. -
What solutions have you tried so far?
I have attempted to use ScreenPointToRay to determine the corners of the camera to get the total size, I have used the ViewPortSize and Field Of View, etc. And no, I have not found much on here in relation to the devforum either.
If anyone is wondering, this is the current code, though it’s not very useful, as I don’t believe this method works:
local CAMERA_OFFSET = (Vector3.yAxis * 2)
local RunService = game:GetService("RunService")
local dialogueMenuUpdatedEvent = game:GetService("Players").LocalPlayer.PlayerGui.UIHandler.DialogueMenuUpdated
local character = script.Parent
local rootPart = character.PrimaryPart
local camera = workspace.CurrentCamera
local zoom = 8
camera.CameraType = Enum.CameraType.Scriptable
local function getCameraSize()
local camera = workspace.CurrentCamera
local topLeft = camera:ViewportPointToRay(0, 0).Origin
local topRight = camera:ViewportPointToRay(camera.ViewportSize.X, 0).Origin
local bottomLeft = camera:ViewportPointToRay(0, camera.ViewportSize.Y).Origin
return (topRight - topLeft).magnitude, (bottomLeft - topLeft).magnitude
end
local function calculateCameraOffset(horizontal)
local camera = workspace.CurrentCamera
local width, height = getCameraSize()
print(width,height)
return if horizontal then Vector3.xAxis * (width * 0.175) else Vector3.yAxis * (height * 0.175)
end
local function updateSplitScreen(enabled, horizontal)
print(enabled)
CAMERA_OFFSET = (Vector3.yAxis * 2) + (if enabled then calculateCameraOffset(horizontal) else Vector3.zero)
end
RunService:BindToRenderStep("UpdateCamera", Enum.RenderPriority.Character.Value , function()
if not character.Parent then RunService:UnbindFromRenderStep("UpdateCamera") end
camera.CFrame = CFrame.lookAt(rootPart.Position + (Vector3.one * zoom), rootPart.Position) * CFrame.new(CAMERA_OFFSET)
end)
dialogueMenuUpdatedEvent.Event:Connect(updateSplitScreen)
updateSplitScreen(true, (camera.ViewportSize.X > camera.ViewportSize.Y))
Hi! Correct me if I am wrong but do you think you can use this to help you adjust the screen size? I can’t remember when I came across this solution, I will try to find the link if it helps. I don’t know if you particularly need to calculate 3D space as you can probably achieve the same, in 2D space.
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
x = mouse.ViewSizeX
y = mouse.ViewSizeY
print(x,y)
The camera itself needs to be offset in 3D space for the effect to work:
The camera is centered on the main character, but since the UI cover up 35% of the screen, it is not centered relative to what the player can actually see. I would like to center the camera on the character in the space still available (hence the offset, and why I need to move the camera itself).
Moving the actual game Viewport via Udim2 or any other method isn’t something doable, as the game Viewport isn’t an actual UI object. What you’re showing me is also identical to Camera.ViewportSize (which is already used in the offset calculation). While I really do appreciate the help, this doesn’t do much to solve it.
The issue seems to be with camera:ViewportPointToRay, surprisingly enough, as they’re all weirdly clumped together, completely unlike their intended origin behavior of appearing on the edges?
The values are the following, if anyone is interested:
topLeft (green): -0.13548733294010162, 8.113245964050293, 5.029464244842529
topRight (yellow): 0.13548733294010162, 8.113245964050293, 5.029464244842529
bottomLeft (red): -0.13548733294010162, 8.003891944885254, 5.116947650909424
You can loop through the UIs that are shown on the players screen and then calculate the edges of the viewable area and shift the camera based on that
These are not ViewportFrames, there is only one Camera. The actual UI that covers the screen is meant to be a toggle-able chat log, but due to its prevalence in the game, offsetting the camera is the only real way to make it enjoyable and non-clunky to play.
The problem with calculating the edges for the camera here is that I do not know of a good method of doing this, and as you can see in the above reply, the current method is not working as intended.
The UIs have position and size properties so you can calculate their edges and then use the closest edge s to the center to calculate how much the camera should be offset
If you are suggesting calculating the difference between edges for the UI element (top left to top right for example), how would I go about converting the returned pixel values into studs, for use in the camera offset Vector3?
Make it proportional to the zoom of the camera and then try multiplying it by different constants
Could you please provide example code on how this could be done, by any chance?