Its work until the camera is behind you, i honestly don't know how to re approach this, so i'm asking the people!
this is the script below,
testLabel is the indicator testLabel2 is where this object is on the screen
local runService = game:GetService("RunService") local players = game:GetService("Players") local player = players.LocalPlayer local mouse = player:GetMouse() local camera = game.Workspace.CurrentCamera local gui = script.Parent local frame = gui:WaitForChild("Frame") local testObject = game.Workspace:WaitForChild("Player 123") local testLabel = frame:WaitForChild("TextLabel") local testLabel2 = frame:WaitForChild("OnScreenPos") runService.RenderStepped:connect(function() local screenPos, show = camera:WorldToScreenPoint(testObject.CFrame.p) local editedPos = UDim2.new(0,0,0,0) --z = the side of screen local behiden = screenPos.z < 0 and true or false if behiden then --screenPos = screenPos * -1 end local y = screenPos.y y = math.clamp(y, 0,gui.AbsoluteSize.Y) local x = screenPos.x x = math.clamp(x, 0,gui.AbsoluteSize.X-10) if not show then if screenPos.X <= 0 then editedPos = UDim2.new(0,0,0,y) elseif screenPos.X >= gui.AbsoluteSize.X then editedPos = UDim2.new(1,-10,0,y) end if screenPos.Y <= 0 then editedPos = UDim2.new(0, x, 0, 0) elseif screenPos.Y >= gui.AbsoluteSize.Y then editedPos = UDim2.new(0, x, 1, -10) end end testLabel.Position = editedPos testLabel2.Position = UDim2.new(0,screenPos.x,0,screenPos.y) end)
I did some looking around and found this Unity forum post https://forum.unity.com/threads/camera-worldtoscreenpoint-bug.85311/ The final post by Alturis2 had some C# code that looked like it would do what you need, so I converted it to Lua and tried it out and it seems to work really well. The ScreenPointEdgeClamp function even returns a rotation value so that you can rotate the offscreen indicator to point to the object being tracked as well as follow it around the edge of the screen.
In the following code, I set things up how I think you have them - ScreenGui/Frame/2 TextLabels, with the LocalScript parented to the ScreenGui. You can obviously use ImageLabels or whatever you want. I also commented in the code where you can adjust how far from the edge of the screen you want the offscreen indicator. Hope this helps.
local RunService = game:GetService("RunService") local Players = game:GetService("Players") local mouse = Players.LocalPlayer:GetMouse() local camera = workspace.CurrentCamera local gui = script.Parent local frame = gui:WaitForChild("Frame") local testObject = workspace:WaitForChild("Part") local onScreenLabel = frame:WaitForChild("OnScreenPos") local offScreenLabel = frame:WaitForChild("OffScreenPos") -- Change this value to determine how far the offscreen indicator remains from the sides of the screen local edgeBuffer = 30 local function Dot(v1, v2) return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z end local function WorldToScreenPointProjected(worldPos) local camNormal = camera.CFrame.lookVector local vectorFromCam = worldPos - camera.CFrame.p local camNormDot = Dot(camNormal, vectorFromCam) if camNormDot <= 0 then -- Object is behind the camera forward facing place. Project the position in front of the plane local proj = camNormal * camNormDot * 1.01 worldPos = camera.CFrame.p + (vectorFromCam - proj) end return camera:WorldToScreenPoint(worldPos) end local function ScreenPointEdgeClamp(screenPos, buffer) -- Take the direction of the screen point from the screen center to push it out to the edge of the screen -- Use the shortest distance from projecting it along the height and width local screenCenter = Vector2.new(gui.AbsoluteSize.X / 2, gui.AbsoluteSize.Y / 2) local screenDir = (screenPos - screenCenter).Unit local angleRad = math.atan2(screenDir.X, screenDir.Y) local distHeight = math.abs((screenCenter.Y - buffer) / math.cos(angleRad)) local distWidth = math.abs((screenCenter.X - buffer) / math.cos(angleRad + (math.pi * 0.5))) local dist = math.min(distHeight, distWidth) local angleDeg = -math.deg(angleRad) return screenCenter + (screenDir * dist), angleDeg end RunService.RenderStepped:connect(function() local position, isVisible = WorldToScreenPointProjected(testObject.Position) if not isVisible then onScreenLabel.Visible = false offScreenLabel.Visible = true local clampedPosition, angle = ScreenPointEdgeClamp(Vector2.new(position.X, position.Y), edgeBuffer) offScreenLabel.Position = UDim2.new(0, clampedPosition.X - offScreenLabel.Size.X.Offset / 2, 0, clampedPosition.Y - offScreenLabel.Size.Y.Offset / 2) offScreenLabel.Rotation = angle else onScreenLabel.Visible = true offScreenLabel.Visible = false onScreenLabel.Position = UDim2.new(0, position.X - onScreenLabel.Size.X.Offset / 2, 0, position.Y - onScreenLabel.Size.Y.Offset / 2) end end)