Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

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

Asked by
lolzmac 207 Moderation Voter
4 years ago
Edited 4 years ago

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

Log in to vote
1
Answered by
noammao 294 Moderation Voter
4 years ago
Edited 4 years ago

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.

0
This helped a lot, thanks! lolzmac 207 — 4y
0
Would also really appreciate if you could upvote my answer thanks :) noammao 294 — 4y
Ad

Answer this question