Let’s create a RadarFrame, which ClipsDescendant (so it cuts off points outside the frame).
Let’s also create a RadarPoint, which indicates a ‘thing’ (but also, the center of the radar to indicate the player).
Time for some maths and logic. Here’s what we’ll need to do.
- We need to store all objects which should show up on the radar, including the origin (the player)
- We need to get the offset from the origin to every point, every frame
- We need to convert from 3 dimensions (the world) to 2 dimensions (the radar). We’re going to do this by simply ignoring the up-axis. Note: Roblox uses Y as the up axis, so from the 3D world we’ll be using X,Z positions but in the 2D radar we’ll be using X,Y where Y is exchanged for our Z (but still called Y)
- We need to multiply this distance by some kind of ratio. For instance, our radar could be 1:200, which means we should multiply by 200. This is our final offset.
- We need to set every point to the originPoint’s position, plus the offset
Let’s create a folder in workspace called Points, in which each child (parts) will be a point. Let’s also store our character, and add a wait (for loading purposes, this is a very crude solution)
Let’s write a function getOffset where we get the offset from origin to object. To do this, we have to get the object’s position and subtract the origin position
Let’s also add a radarPoint for every object. Of course we already have 1 radarpoint for the player, in the RadarFrame by default. This point is just centered.
wait(3)
local Objects = game.Workspace.Points:GetChildren()
local Origin = game.Players.LocalPlayer.Character.HumanoidRootPart
local RadarFrame = game.Players.LocalPlayer.PlayerGui.ScreenGui.RadarFrame
local RadarPoints = {}
for i,v in ipairs(Objects) do
local newPoint = game.ReplicatedStorage.RadarPoint:Clone()
newPoint.Parent = RadarFrame
table.insert(RadarPoints,newPoint)
end
local function getOffset(obj)
local xOrigin,yOrigin = Origin.Position.X,Origin.Position.Z -- Note we can use the Z position as our Y, so we don't have to deal with it later
local xTarget,yTarget = obj.Position.X,obj.Position.Z
local xOffset,yOffset = xTarget-xOrigin,yTarget-yOrigin
return Vector2.new(xOffset,yOffset)
end
Let’s add the gameloop. In the loop we will get every object, and print their offset. For now I will just use 1 object, so that it’s easy to debug.
game:GetService("RunService").RenderStepped:Connect(function(dt)
for i,v in ipairs(Objects) do
print(getOffset(v))
end
end)
So it works, and you can imagine that if my character is the dot, then we have to move offset to get to the point. Let’s translate this to the UI.
First, we’ll need to decide on a ratio. Let’s do 1:2. So our convertedOffset = offset*2. Then we get the radarPoint, and add this to it’s position. Of course, UI elements work with UDim’s (not Vector2’s) so we’ll need to keep that in mind. A centered point will have a position of Udim2.new(0.5,0,0.5,0). We can simply replace the offset values with our new calculated ones.
game:GetService("RunService").RenderStepped:Connect(function(dt)
for i,v in ipairs(Objects) do
print(getOffset(v))
local convertedOffset = getOffset(v)
local radarPoint = RadarPoints[i]
radarPoint.Position = UDim2.new(0.5,convertedOffset.X,0.5,convertedOffset.Y)
end
end)
Uploading: 6721e95735e4efc88c6dba6876566706.gif…
Now a problem arises: the radar needs to be rotated in the direction of the camera, otherwise it’s not very useful. Okay, time for some more math.
We’re going to get the angle between the up-vector and the direction you’re looking in. The red is the up vector. The blue is what we’re going to calculate. At angle 0, the radar should be pointing directly ‘north’. At 180, it’s pointing south. In the example, the blue is at 130 degrees (this is just to give you an example)
We do this by getting the vector from the camera to the player. This is the direction you’re looking in, because the player is always in the center of the screen (if you move your camera from the player in a cutscene, this’ll break until it’s back).
local function updateRadar()
local relativePosition = Origin.Position - Camera.CFrame.Position
local angle = math.atan2(relativePosition.z, relativePosition.x) -- Calculate angle
RadarFrame.Rotation = -(math.deg(angle) + 90) -- Set UI rotation
end
So after ever radarPoint has been calculated we updateRadar().
The result is this.
Edit:
As per personal request, here’s the file. I did make some adjustments later, namely that the dots are the same size as the objects, and take their colour.
RadarTest.rbxl (59.5 KB)