i want to make a gps system inside a ui for my game. But i have absolutely no idea how to start making it. Can anyone help me or reference a general idea on the logic and how do i make this gps system.
here’s an example
alternatively, (i prefer not to use complicated algorithms) how do i make an arrow pointing to a “destination” or a waypoint inside a ui
A frame containing the map itself.
The map can then be an image/whatever, however you need to make it a child of the frame and turn on ClipsDescendants for both of them, so it basically snips the map to fit the frame.
For the map, you could either use a pre-rendered image or a ViewportFrame of the map; ViewportFrames are more expensive but can update real time, however pre-rendered images are cheaper but would need to be updated every time a change is made to your map
For the player and it all to move, you’d need to be able to map the player’s location to a location of the UI; which should be pretty simple. If you know (0, 0) of the UI corresponds to, say, (-100, 0, -100) in the world and (1, 1) corresponds to (100, 0, 100), then it’s simple maths to figure out where in the world corresponds to where on the UI. You could then make it so when the player clicks on the map, it just does the maths in reverse to find where from the UI the map is in the world
Finally, to make, as you described, an arrow, its just a bit more maths. You could use CFrame:lookAt() to find how to look from the player to the destination, and then move it two studs forwards (from what i remember, cframe * CFrame.new(-2, 0, 0) to move it 2 studs forwards)
Let me know if you need any clarification or help writing the code or anything
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local RepStorage = game:GetService("ReplicatedStorage")
local frame = script.Parent
local camera = workspace.CurrentCamera
local viewportFrame = frame.ViewportFrame
local playerIndicatorTemplate = frame.Player
local pixelsPerStud = 3.69
playerIndicatorTemplate.Parent = nil
local waypoint = workspace.Visual:WaitForChild("Node")
local waypointUI = viewportFrame.Waypoint
for _, descendant in pairs(workspace.Visual.Map:GetDescendants()) do
if descendant:IsA("BasePart") == false then continue end
local clone = descendant:Clone()
clone.Parent = viewportFrame
end
local viewportCamera = Instance.new("Camera")
viewportCamera.FieldOfView = 20
viewportFrame.CurrentCamera = viewportCamera
-- Minimap variables
local offset, chunkSize, chunkHalfSize, currentX, currentZ
local playerIndicators = {}
local function UpdateMinimap()
local focusX = camera.Focus.Position.X / chunkSize
local focusZ = camera.Focus.Position.Z / chunkSize
local chunkX, chunkZ = math.floor(focusX), math.floor(focusZ)
local x, z = focusX % 1, focusZ % 1
if currentX ~= chunkX or currentZ ~= chunkZ then
currentX, currentZ = chunkX, chunkZ
local position = Vector3.new(chunkX * chunkSize + chunkHalfSize, 0, chunkZ * chunkSize + chunkHalfSize)
viewportCamera.CFrame = CFrame.lookAt(position + offset, position, -Vector3.zAxis)
end
viewportFrame .Position = UDim2.new(1 - x, 0, 1 - z, 0)
end
local function UpdatePlayers()
local focusX = camera.Focus.Position.X / chunkSize
local focusZ = camera.Focus.Position.Z / chunkSize
for player, gui in pairs(playerIndicators) do
if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
local cFrame = player.Character:GetPivot()
local x, z = cFrame.Position.X / chunkSize, cFrame.Position.Z / chunkSize
gui.Position = UDim2.new(0.5 - focusX + x, 0, 0.5 - focusZ + z, 0)
gui.Rotation = -player.Character.HumanoidRootPart.Orientation.Y
end
end
end
local function PlayerAdded(player)
if player == game.Players.LocalPlayer then
local gui = playerIndicatorTemplate:Clone()
gui.PlayerName.Text = ""
gui.Parent = frame
playerIndicators[player] = gui
else
local gui = playerIndicatorTemplate:Clone()
gui.PlayerName.Text = player.Name
gui.Parent = frame
playerIndicators[player] = gui
end
end
-- Player leaves: Remove from minimap
local function PlayerRemoving(player)
if playerIndicators[player] then
playerIndicators[player]:Destroy()
playerIndicators[player] = nil
end
end
local function SetMinimapZoom(value)
offset = Vector3.new(0, value, 0)
chunkSize = offset.Y * math.tan(math.rad(viewportCamera.FieldOfView) / 2)
chunkHalfSize = chunkSize / 2
currentX, currentZ = math.huge, math.huge
UpdateMinimap()
end
RunService.RenderStepped:Connect(function()
UpdatePlayers()
local player = Players.LocalPlayer
local playerIndicator = playerIndicators[player]
if player.Character and player.Character.PrimaryPart and playerIndicator then
local direction = waypoint.Position - player.Character.PrimaryPart.Position
local direction2D = Vector2.new(direction.X, direction.Z)
local currentPixelsPerStud = pixelsPerStud * (offset.Y / 500) -- Adjust multiplier based on default zoom
local posOnMap = playerIndicator.Position + UDim2.new(0, direction2D.X * currentPixelsPerStud, 0, direction2D.Y * currentPixelsPerStud)
waypointUI.Position = posOnMap
end
end)
SetMinimapZoom(650)
camera:GetPropertyChangedSignal("Focus"):Connect(UpdateMinimap)
for _, player in pairs(Players:GetPlayers()) do PlayerAdded(player) end
Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)
i already made all the previous steps (before the arrow one), but i still don’t understand how would i use the cframe look at to make the arrow (inside the gui), can you elaborate more?