I’m creating a minimap that will display units with humanoids in the workspace as blue dots on a frame. And translate their world coordinates to the frame coords. But I can’t seem to get it right, the X and Z size represents the battle field width and length.
Right now the blue dots are too far top right and outside the frame. Any ideas?
local MAP_SIZE_X = 1201.5
local MAP_SIZE_Z = 531.6
local MINIMAP_SIZE = 150
local UNIT_SIZE = 5
-- Create the ScreenGui to hold the minimap
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "MinimapGui"
screenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
-- Create the frame for the minimap
local minimapFrame = Instance.new("Frame")
minimapFrame.Name = "MinimapFrame"
minimapFrame.Size = UDim2.new(0, MINIMAP_SIZE, 0, MINIMAP_SIZE)
minimapFrame.Position = UDim2.new(0.5, -MINIMAP_SIZE / 2, 0.5, -MINIMAP_SIZE / 2)
minimapFrame.BackgroundTransparency = 0.5
minimapFrame.BackgroundColor3 = Color3.new(0, 0, 0)
minimapFrame.BorderSizePixel = 2
minimapFrame.BorderColor3 = Color3.new(0, 0, 1)
minimapFrame.AnchorPoint = Vector2.new(0.5, 0.5) -- Ensure that the frame is centered
minimapFrame.Parent = screenGui
-- Create a function to update the minimap
local function updateMinimap()
-- Get all the units in the game
local units = game:GetService("Workspace"):GetDescendants()
local unitList = {}
for i, unit in ipairs(units) do
if unit:IsA("BasePart") and unit.Name == "HumanoidRootPart" then
table.insert(unitList, unit)
end
end
-- Update the minimap to show all the units
local minimap = minimapFrame:FindFirstChild("Minimap")
if not minimap then
minimap = Instance.new("Frame")
minimap.Name = "Minimap"
minimap.Size = UDim2.new(1, 0, 1, 0)
minimap.BackgroundTransparency = 1
minimap.Parent = minimapFrame
end
for i, unit in ipairs(unitList) do
-- Calculate the position of the unit on the minimap
local x = ((unit.Position.X + (MAP_SIZE_X / 2)) / MAP_SIZE_X) * MINIMAP_SIZE
local y = ((unit.Position.Z + (MAP_SIZE_Z / 2)) / MAP_SIZE_Z) * MINIMAP_SIZE
-- Create or update the unit's circle on the minimap
local unitCircle = minimap:FindFirstChild("Unit" .. i)
if not unitCircle then
unitCircle = Instance.new("Frame")
unitCircle.Name = "Unit" .. i
unitCircle.Size = UDim2.new(0, UNIT_SIZE, 0, UNIT_SIZE)
unitCircle.BackgroundColor3 = Color3.new(0, 0, 1)
unitCircle.BorderSizePixel = 0
unitCircle.Parent = minimap
end
unitCircle.Position = UDim2.new(0, x - UNIT_SIZE / 2, 0, y - UNIT_SIZE / 2)
end
end
-- Connect the updateMinimap function to the Heartbeat event
game:GetService("RunService").Heartbeat:Connect(updateMinimap)
-- Add the screenGui to the player's PlayerGui
screenGui.Parent = game:GetService("Players").LocalPlayer.PlayerGui
The reason why MAP_SIZE / 2 is added to the unit position is to ensure that the position of the unit is relative to the center of the map, rather than the corner of the map.
Since the minimap is a smaller representation of the entire game map, it needs to be scaled down and centered properly to show the correct positions of all the units. The MAP_SIZE_X and MAP_SIZE_Z variables represent the size of the entire game map in the X and Z dimensions. By adding half of the MAP_SIZE_X and MAP_SIZE_Z values to the X and Z coordinates of the unit’s position, the resulting position is relative to the center of the map, which allows the minimap to correctly show the positions of all the units in the game.
Edit: at least this is what chatgpt told me to do. I was partly editing an old script which used a viewport frame to display models in the game. But doing that was super laggy, so I switched to try and use small frames to represent players in the game. But my math isn’t good enough to figure this out properly, so been using chatgpt for the math side but it can’t get it right.
To translate the world coordinates of the units to the frame coordinates of the minimap, you need to use some math to scale down the world coordinates to fit within the size of the minimap frame.
Example u could use to do this:
-- loop through all humanoid units in workspace
for _, unit in pairs(workspace:GetDescendants()) do
if unit:IsA("Model") and unit:FindFirstChild("Humanoid") then
-- Create a blue dot for the unit
local unitDot = Instance.new("Frame")
unitDot.Size = UDim2.new(0, UNIT_SIZE, 0, UNIT_SIZE)
unitDot.BackgroundColor3 = Color3.new(0, 0, 1)
unitDot.BorderSizePixel = 0
unitDot.Parent = minimapFrame
-- translate the world coordinates of the unit to the frame coordinates of the minimap
local unitPos = unit.PrimaryPart.Position
local frameX = (unitPos.X / MAP_SIZE_X) * MINIMAP_SIZE
local frameZ = (unitPos.Z / MAP_SIZE_Z) * MINIMAP_SIZE
unitDot.Position = UDim2.new(0, frameX, 0, frameZ)
end
end
local MAP_SIZE_X = 364
local MAP_SIZE_Z = 1192.16
local MINIMAP_SIZE = 250
local UNIT_SIZE = 5
-- Create the ScreenGui to hold the minimap
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "MinimapGui"
screenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
-- Create the frame for the minimap
local minimapFrame = Instance.new("Frame")
minimapFrame.Name = "MinimapFrame"
minimapFrame.Size = UDim2.new(0, MINIMAP_SIZE, 0, MINIMAP_SIZE)
minimapFrame.Position = UDim2.new(0.5, -MINIMAP_SIZE / 2, 0.5, -MINIMAP_SIZE / 2)
minimapFrame.AnchorPoint = Vector2.new(0.5, 0.5) -- Set the anchor point to the center of the frame
minimapFrame.BackgroundTransparency = 0.5
minimapFrame.BackgroundColor3 = Color3.new(0, 0, 0)
minimapFrame.BorderSizePixel = 2
minimapFrame.BorderColor3 = Color3.new(0, 0, 1)
--minimapFrame.ClipsDescendants = true
minimapFrame.Parent = screenGui
function newUpdate()
for _, unit in pairs(workspace:GetDescendants()) do
if unit:IsA("Model") and unit:FindFirstChild("Humanoid") then
-- Create a blue dot for the unit
local unitDot = Instance.new("Frame")
unitDot.Size = UDim2.new(0, UNIT_SIZE, 0, UNIT_SIZE)
unitDot.BackgroundColor3 = Color3.new(0, 0, 1)
unitDot.BorderSizePixel = 0
unitDot.Parent = minimapFrame
-- translate the world coordinates of the unit to the frame coordinates of the minimap
local unitPos = unit.PrimaryPart.Position
local frameX = (unitPos.X / MAP_SIZE_X) * MINIMAP_SIZE
local frameZ = (unitPos.Z / MAP_SIZE_Z) * MINIMAP_SIZE
unitDot.Position = UDim2.new(0, frameX, 0, frameZ)
end
end
end
game:GetService("RunService").Heartbeat:Connect(newUpdate)
screenGui.Parent = game:GetService("Players").LocalPlayer.PlayerGui
function newUpdate()
-- Calculate the position of the camera in the minimap frame
local camPos = workspace.CurrentCamera.CFrame.p
local frameX = (camPos.x / MAP_SIZE_X) * MINIMAP_SIZE
local frameZ = (camPos.z / MAP_SIZE_Z) * MINIMAP_SIZE
-- Update the position of the minimap frame to center around the camera
minimapFrame.Position = UDim2.new(0.5, -MINIMAP_SIZE / 2 + frameX, 0.5, -MINIMAP_SIZE / 2 + frameZ)
-- Update the positions of the unit dots
for _, unitDot in ipairs(minimapFrame:GetChildren()) do
if unitDot:IsA("Frame") then
local unit = unitDot.Parent
if unit:IsA("Model") and unit:FindFirstChild("Humanoid") then
local unitPos = unit.PrimaryPart.Position
local dotX = (unitPos.x / MAP_SIZE_X) * MINIMAP_SIZE
local dotZ = (unitPos.z / MAP_SIZE_Z) * MINIMAP_SIZE
unitDot.Position = UDim2.new(0, dotX - frameX, 0, dotZ - frameZ)
end
end
end
end
This version of newUpdate first calculates the position of the camera in the minimap frame using the same formula as before. Then it updates the position of the minimap frame to center around the camera. it updates the positions of the unit dots relative to the camera position, so they stay in the same position on the minimap even as the camera moves.
To fix the issue with the blue dots being outside the minimap frame, you need to adjust the calculation for the position of each unit on the minimap. The current calculation is based on the size of the minimap frame, but it does not take into account the position of the frame itself.
To fix this, you can add the position of the minimap frame to the x and y values calculated for each unit’s position. Here is the updated code for the updateMinimap function:
local function updateMinimap()
-- Get all the units in the game
local units = game:GetService("Workspace"):GetDescendants()
local unitList = {}
for i, unit in ipairs(units) do
if unit:IsA("BasePart") and unit.Name == "HumanoidRootPart" then
table.insert(unitList, unit)
end
end
-- Update the minimap to show all the units
local minimap = minimapFrame:FindFirstChild("Minimap")
if not minimap then
minimap = Instance.new("Frame")
minimap.Name = "Minimap"
minimap.Size = UDim2.new(1, 0, 1, 0)
minimap.BackgroundTransparency = 1
minimap.Parent = minimapFrame
end
-- Get the position of the minimap frame
local minimapPosition = minimapFrame.AbsolutePosition
for i, unit in ipairs(unitList) do
-- Calculate the position of the unit on the minimap
local x = ((unit.Position.X + (MAP_SIZE_X / 2)) / MAP_SIZE_X) * MINIMAP_SIZE + minimapPosition.X
local y = ((unit.Position.Z + (MAP_SIZE_Z / 2)) / MAP_SIZE_Z) * MINIMAP_SIZE + minimapPosition.Y
-- Create or update the unit's circle on the minimap
local unitCircle = minimap:FindFirstChild("Unit" .. i)
if not unitCircle then
unitCircle = Instance.new("Frame")
unitCircle.Name = "Unit" .. i
unitCircle.Size = UDim2.new(0, UNIT_SIZE, 0, UNIT_SIZE)
unitCircle.BackgroundColor3 = Color3.new(0, 0, 1)
unitCircle.BorderSizePixel = 0
unitCircle.Parent = minimap
end
unitCircle.Position = UDim2.new(0, x - UNIT_SIZE / 2, 0, y - UNIT_SIZE / 2)
end
end
This should correctly position the blue dots on the minimap frame.
local MAP_SIZE_X = 364
local MAP_SIZE_Z = 1192.16
local MINIMAP_SIZE = 250
local UNIT_SIZE = 5
-- Create the ScreenGui to hold the minimap
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "MinimapGui"
screenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
-- Create the frame for the minimap
local minimapFrame = Instance.new("Frame")
minimapFrame.Name = "MinimapFrame"
minimapFrame.Size = UDim2.new(0, MINIMAP_SIZE, 0, MINIMAP_SIZE)
minimapFrame.Position = UDim2.new(0.5, -MINIMAP_SIZE / 2, 0.5, -MINIMAP_SIZE / 2)
minimapFrame.AnchorPoint = Vector2.new(0.5, 0.5) -- Set the anchor point to the center of the frame
minimapFrame.BackgroundTransparency = 0.5
minimapFrame.BackgroundColor3 = Color3.new(0, 0, 0)
minimapFrame.BorderSizePixel = 2
minimapFrame.BorderColor3 = Color3.new(0, 0, 1)
--minimapFrame.ClipsDescendants = true
minimapFrame.Parent = screenGui
local function newUpdateMinimap()
-- Get all the units in the game
local units = game:GetService("Workspace"):GetDescendants()
local unitList = {}
for i, unit in ipairs(units) do
if unit:IsA("BasePart") and unit.Name == "HumanoidRootPart" then
table.insert(unitList, unit)
end
end
-- Update the minimap to show all the units
local minimap = minimapFrame:FindFirstChild("Minimap")
if not minimap then
minimap = Instance.new("Frame")
minimap.Name = "Minimap"
minimap.Size = UDim2.new(1, 0, 1, 0)
minimap.BackgroundTransparency = 1
minimap.Parent = minimapFrame
end
-- Get the position of the minimap frame
local minimapPosition = minimapFrame.AbsolutePosition
for i, unit in ipairs(unitList) do
-- Calculate the position of the unit on the minimap
local x = ((unit.Position.X + (MAP_SIZE_X / 2)) / MAP_SIZE_X) * MINIMAP_SIZE + minimapPosition.X
local y = ((unit.Position.Z + (MAP_SIZE_Z / 2)) / MAP_SIZE_Z) * MINIMAP_SIZE + minimapPosition.Y
-- Create or update the unit's circle on the minimap
local unitCircle = minimap:FindFirstChild("Unit" .. i)
if not unitCircle then
unitCircle = Instance.new("Frame")
unitCircle.Name = "Unit" .. i
unitCircle.Size = UDim2.new(0, UNIT_SIZE, 0, UNIT_SIZE)
unitCircle.BackgroundColor3 = Color3.new(0, 0, 1)
unitCircle.BorderSizePixel = 0
unitCircle.Parent = minimap
end
unitCircle.Position = UDim2.new(0, x - UNIT_SIZE / 2, 0, y - UNIT_SIZE / 2)
end
end
-- Connect the updateMinimap function to the Heartbeat event
game:GetService("RunService").Heartbeat:Connect(newUpdateMinimap)
-- Add the screenGui to the player's PlayerGui
screenGui.Parent = game:GetService("Players").LocalPlayer.PlayerGui