Can someone help me with my mini map script?

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

Why do you add MAP_SIZE / 2 to the unit position?

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

Hey thanks, I’m still having the same issue.

https://gyazo.com/67e7dd4629b7d585965793bb613e17e0 (Ignore the constant blue line as I didn’t update the code to account for units that already existed, but they are all outside the frame)

Here is my part that I used for the map size X and Z
https://gyazo.com/eda6a176c3a519612187ce8f15126c86

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

Any ideas?
////////////////////////////////

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.

No such luck, current code with your addition:
https://gyazo.com/dac1475bbee186051f7daf211208cdab

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

This isn’t what I’m trying to achieve. If you ever played Warcraft 3 I’m trying to replicate their minimap system.