Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

[SOLVED] How to have a 2D GUI arrow point at a Worldpoint object off screen?

I'm trying to make an arrow pop up on the edge of your screen pointing to the direction that a certain object is. I've gotten the Vector2 using Camera:WorldToScreenPoint() but I don't know where to go after that since these vectors are too big. Any ideas?

This is my code so far, that doesn't work how I want it to.

if not onScreen then
	local screenPoint = UDim2.new(vector.X, 0, vector.Y, 0)
	UIMarker = game.Workspace.Markers.Marker1()
	UIMarker.Parent = UI.MarkersUI
	UIMarker.Position = screenPoint
	wait(MarkerTime)
	UIMarker:Destroy()
end

1 answer

✓ Accepted answer

There are multiple ways to do this depending on what you're looking for but I think that this should be okay:

--Variables--
local flag = workspace.Target
local cam = workspace.CurrentCamera
local image = script.Parent.ScreenGui.ImageLabel
local imageId = "http://www.roblox.com/asset/?id=11458585"
local Render = game:GetService("RunService").RenderStepped

while Render:wait() do

--Get the position of the object in screen space
local vector, onScreen = cam:WorldToViewportPoint(flag.Position)

--Get the directional vector between your arrow and the object by using
--Euclidean vectors & Pythagoras theorem in our calculations.
local x1,y1 = vector.X,vector.Y
local x2,y2 = image.Position.X.Offset, image.Position.Y.Offset
local xlength,ylength,zlength = x1-x2,y1-y2,vector.Z
local hypotenuse = math.sqrt(xlength*xlength + ylength*ylength)
local UnitX,UnitY,UnitZ = xlength/hypotenuse, ylength/hypotenuse,zlength/hypotenuse
local Normalized2dDirection = Vector3.new(UnitX,-UnitY,UnitZ)

--Calculate the angle.
--We assume the default arrow position at 0° is "up"
local angle = math.deg(math.acos(Normalized2dDirection:Dot(cam.CFrame.UpVector)))

--Use the cross product to determine if the angle is clockwise
--or anticlockwise
local cross = Normalized2dDirection:Cross(cam.CFrame.UpVector)
local angle2 = math.sign(cross.Z) * angle

--Update the rotation of your arrow.
if onScreen then
image.Image = ""
else image.Image = imageId
image.Rotation = angle2
end

end

This is my first time trying to do anything like this by myself so I had to learn while doing this. It has been quite the ride, but I think that it turned out okay (although I know that it's a bit glitchy & could be improved.

Honestly, I think that it looks better if you remove

if onScreen then
image.Image = ""
else image.Image = imageId
image.Rotation = angle2
end

and just replace it with image.Rotation = angle2.

Here are some links to help: Link1 Link2 Link3.

2 comments

0

This helped a lot, thanks!

0

Would also really appreciate if you could upvote my answer thanks :)

This discussion is preserved as it was. New answers, comments, and votes are closed.