very late bump but currently facing the same exact issue. thank you for providing your code sample. ive managed to fix this.
Looking at your code you’ve done everything correct except for the cornerCFrame part. you’ve calculated the corner according to the center of the part rather then following the same approach as a ui (which is the top left). to fix this you simply gotta add the text label size to the corner and divide it by 2 which fixes the X axis in the process (CFrame.new((textLabel.AbsoluteSize.X * screenRatio.X)/2). we also do the same thing to the Y axis.
Old problem. fixed on the edit
Now the problem ive faced right now which ive partially fixed is the Y axis. for some reason it seems like using the “uiPosition.Y” offsets it the more you modify the screen resolution for the y axis (if you attempt to test between mobile and computer screen. the y axis offsets pretty drastically) despite the fact that the corner alignment is perfect and doesn’t have any offset when testing it.
The work around for this is to use the Y size of the text label and transforming the the text label’s size to pure scale only (doesn’t seem to work if you use offset). then just add an offset to the cornercframe’s Y to align it with the ui. this seems to work perfectly on all kinds of resolutions.
I hope someone could provide an explanation for the Y axis problem.
EDIT:
Figured out whats going on for the y axis. its because the text label is calculating its absolute size/pos in accordance to its parent screen gui which takes into account of things like the gui inset. hense why the offset is happening. to fix this we have to calculate our own absolute position and size. but this time in accordance to the actual viewport extracted off the camera.
this is an example of how it looks like for a text label :
local absoluteSize = Vector2.new(
textLabel.Size.X.Scale * viewportSize.X + textLabel.Size.X.Offset,
textLabel.Size.Y.Scale * viewportSize.Y+ textLabel.Size.Y.Offset
)
local absolutePosition = Vector2.new(
textLabel.Position.X.Scale * viewportSize.X + textLabel.Position.X.Offset,
textLabel.Position.Y.Scale * viewportSize.Y + textLabel.Position.Y.Offset
)
And now from here. we just perform the same exact operation we’ve done to the width. which now becomes :
-(absoluteSize.Y * screenRatio.Y)/2
This is the final version. didn’t have enough time to organize the code sadly but hope this is understandeable enough :
local RunService = game:GetService("RunService")
local camera = game.Workspace.CurrentCamera
local part = game.Workspace.Part
local textLabel = script.Parent.Frame
local function viewportToStuds(viewportSize, depth, absoluteSize)
local aspectRatio = viewportSize.X / viewportSize.Y --Get screen aspect ratio (1920 / 1080)
local heightFactor = math.tan(math.rad(camera.FieldOfView)/2) --Get height of screen from camera
local widthFactor = aspectRatio * heightFactor --Use height to also get the width
local screenSize = Vector2.new(-2 * widthFactor * -depth, -2 * heightFactor * -depth) --Get size of the screen
local screenRatio = Vector2.new(screenSize.X / viewportSize.X, screenSize.Y / viewportSize.Y) --The ratio for pixel to studs
local screenCFrame = camera.CFrame * CFrame.new(0, 0, -depth) --Get where the screen is in the world
local cornerCFrame =
screenCFrame
* CFrame.new(-screenSize.X/2, screenSize.Y/2, 0)
* CFrame.new((absoluteSize.X * screenRatio.X)/2, -(absoluteSize.Y * screenRatio.Y)/2, 0)
--Get the corner of the screen
--part.CFrame = cornerCFrame
return screenSize, screenRatio, cornerCFrame
end
RunService.RenderStepped:Connect(function()
local viewportSize = camera.ViewportSize
local absoluteSize = Vector2.new(
textLabel.Size.X.Scale * viewportSize.X + textLabel.Size.X.Offset,
textLabel.Size.Y.Scale * viewportSize.Y+ textLabel.Size.Y.Offset
)
local absolutePosition = Vector2.new(
textLabel.Position.X.Scale * viewportSize.X + textLabel.Position.X.Offset,
textLabel.Position.Y.Scale * viewportSize.Y + textLabel.Position.Y.Offset
)
local screenSize, screenRatio, cornerCFrame = viewportToStuds(viewportSize, 1, absoluteSize)
part.Size = Vector3.new(absoluteSize.X * screenRatio.X, absoluteSize.Y * screenRatio.Y, 0)
part.CFrame = cornerCFrame * CFrame.new(absolutePosition.X * screenRatio.X, -absolutePosition.Y * screenRatio.Y, 0)
end)