Hey there! I’m trying to find how to get the world position of a frame inside of a SurfaceGUI, but I have no idea whatsoever on how to achieve this. Can anyone help me with this? Any help is appreciated!
local frame3DPosition = workspace.CurrentCamera:ScreenPointToRay(frame.AbsolutePosition.X, frame.AbsolutePosition.Y)
Alternatively :ViewportPointToRay might work better in some cases so I suggest you try both
AbsolutePosition is not going to be relative to the camera - rather, it will be relative to the surface GUI.
This means that your proposed solution will unfortunately not work
Actually technically speaking, wouldn’t the world position of a Frame inside a SurfaceGui inside a Part be the Part’s position? Although if we’re really getting technical it would be dependant on the SurfaceGui’s Face property so if it’s set to Front for example, the world position of the Frame would be: Part.Position + Part.CFrame.LookVector * (a very, very small number like 0.00001)
Although if the part is rotated this formula should work better: (Part.CFrame + Part.CFrame.LookVector * (really small number)).Position
The frame is not taking up the entire part, just a very small portion of it.
The formula I provided (especially the second one) should still work no matter the size of the frame, although you’ll need to remember to change CFrame.LookVector depending on the SurfaceGui’s Face property for it to work correctly
Here’s an example of what I’m trying to do:
In the image, there’s a frame in the top left. I want to get the world position of that frame. If I were to use LookVector, it would return the position in the middle, the neon part.
It could be that I’m doing something wrong, I’m not totally sure how :ScreenPointToRay works.
Here’s the function I made using your line of code:
local function GetGuiPosition(frame)
local finalPosition
local framePosition = workspace.CurrentCamera:ScreenPointToRay(frame.AbsolutePosition.X, frame.AbsolutePosition.Y)
local ray = workspace:Raycast(framePosition.Origin, framePosition.Direction*999, params)
if ray then
finalPosition = ray.Position
end
return finalPosition
end
This gives me a very wrong position, not even close to where the frame is. :ViewportPointToRay does the same thing.
Oh now I see what your goal is, this will be tricky but I think I have a possible solution
It’s taking quite a bit of time to test so instead I’ll explain what you most likely need to do to calculate the result position:
- Calculate Part.Size.X * SurfaceGui.PixelsPerStud (Answer1) and Part.Size.Y * SurfaceGui.PixelsPerStud (Answer2)
- Calculate relative Frame percentage by doing: Frame.AbsoluteSize.X / Answer1 and Frame.AbsoluteSize.Y / Answer2
- Convert the frame percentages back to studs instead of pixels
- Use the answers to calculate the offset relative to the SurfaceGui Part
Edit: @ColdFoxy07 this is the closest I’ve gotten to your goal (it’s not pretty, I know):
local part = workspace.Part
local gui = part.SurfaceGui
local frame = gui.Frame
local a = part.Size.X * gui.PixelsPerStud
local b = part.Size.Y * gui.PixelsPerStud
print(a, b)
local c = frame.AbsoluteSize.X / a
local d = frame.AbsoluteSize.Y / b
print(c, d)
local cframe = part.CFrame
local p0 = (cframe + (cframe.UpVector * part.Size.Y / 2 + -cframe.RightVector * part.Size.X / 2)).Position
local p1 = (cframe + (-cframe.UpVector * part.Size.Y / 2 + cframe.RightVector * part.Size.X / 2)).Position
warn(p0, p1)
warn(p0:Lerp(p1, c / 2))
warn(p0:Lerp(p1, d / 2))
Works best if the Frame is a square, and if so the last line isn’t required
Edit2: With this mod it’s now accepting rectangles as well:
local part = workspace.Part
local gui = part.SurfaceGui
local frame = gui.Frame
local a = part.Size.X * gui.PixelsPerStud
local b = part.Size.Y * gui.PixelsPerStud
print(a, b)
local c = frame.AbsoluteSize.X / a
local d = frame.AbsoluteSize.Y / b
print(c, d)
local cframe = part.CFrame
local p0 = (cframe + (cframe.UpVector * part.Size.Y / 2 + -cframe.RightVector * part.Size.X / 2)).Position
local p1 = (cframe + (-cframe.UpVector * part.Size.Y / 2 + cframe.RightVector * part.Size.X / 2)).Position
warn(p0, p1)
local p2 = p0:Lerp(p1, c / 2)
local p3 = p0:Lerp(p1, d / 2)
warn(p2.X, p3.Y, p2.Z)
Thanks! But, what exactly is the world position of the frame here? This is all very confusing to me
Essentially to test it I placed a 1, 1, 1 sized part exactly in the middle of the Frame like so:
And made sure that the formula gives a result that matches its position
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.