Tried this, but it's trash
cam = workspace.CurrentCamera while wait() do sunDirection = game.Lighting:GetSunDirection() camDirection = cam.CoordinateFrame.lookVector sunDirectionXZPlane = Vector3.new(sunDirection.X,0,sunDirection.Z).unit camDirectionXZPlane = Vector3.new(camDirection.X,0,camDirection.Z).unit camDirectionYPlane = Vector3.new(sunDirection.X,camDirection.Y,sunDirection.Z).unit angleLeftRight = math.acos(camDirectionXZPlane:Dot(sunDirectionXZPlane)) angleUpDown = math.acos(camDirectionYPlane:Dot(sunDirection)) angle = math.acos(camDirection:Dot(sunDirection)) print(angle) script.Parent.Position = UDim2.new(angleLeftRight+0.5,-25,angleUpDown+0.5,-25) end
You don't need to do the math yourself (you'd rather not because of field of view and unknown screen ratio).
The Camera object provides a helpful WorldToScreenPoint method.
local sunPosition = camera.CoordinateFrame.p + game.Lighting:GetSunDirection() * 10 -- get the position of the sun in the world. -- how far away it is (the 10) shouldn't really matter. local screenPosition = camera:WorldToScreenPoint( sunPosition ) script.Parent.Position = UDim2.new(0, screenPosition.x, 0, screenPosition.y)
And that's all there is to it! (EDIT: tested it, it works)
If you're curious about the math behind WorldToScreenPoint
, it works something like this:
Take a point in the world, move it into the object space of the camera, then divide by depth:
local p = camera.CoordinateFrame:PointToObjectSpace( worldPoint ) p = p / p.z
Now you have to scale to fit the FieldOfView in the height of the screen.
local maxY = math.tan( FieldOfView / 2 ) p = p / maxY
Now you have to multiply by the screen size and center.
The PointToObjectSpace
calculation works like this:
local cam = camera.CoordinateFrame D = worldPoint - cam.p local fwd, right, up = cam:VectorToWorldSpace(0, 0, -1), ... local p = Vector3.new( right:Dot(D), up:Dot(D), fwd:Dot(D) )