Im trying to make a small icon indicator for a 3D minimap however the problem is when I convert the 3D coords from the viewportframe into 2D cords for the screen/Ui the positions seem to be wrong so obviously Im doing something wrong. From the clip you can see position the small little grey icons have are wrong they don’t follow the objects in the viewportframe quite right and near the edges it cuts off a little early suggesting theres an error in cords im getting.
here is the code
local player = game.Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local viewportFrame = playerGui:WaitForChild("ScreenGui").Frame.ViewportFrame
local dragger = playerGui.ScreenGui.Frame.Dragger -- The frame to drag
local planetsFolder = viewportFrame:WaitForChild("Planets") -- Get the planets folder
local camera = Instance.new("Camera") -- Create a new camera
viewportFrame.CurrentCamera = camera -- Set the viewport frame's camera
-- Create ImageButtons for each planet (model or part)
local imageButtons = {}
local function createImageButton(planet)
local imageButton = Instance.new("ImageButton")
imageButton.Size = UDim2.new(0, 10, 0, 10)
imageButton.Parent = playerGui.ScreenGui.Frame
imageButton.Visible = true
imageButtons[planet.Name] = imageButton
end
-- Iterate through planets and create ImageButtons
for _, planet in ipairs(planetsFolder:GetChildren()) do
if planet:IsA("Model") or planet:IsA("Part") then
createImageButton(planet)
end
end
local distanceFromPlanet = 6000 -- Distance from the central object
local originalPosition = dragger.Position -- Store the original position
local dragging = false
local lastMousePosition = nil
local horizontalRotation = math.rad(90) -- Starting angle for horizontal rotation
local verticalRotation = 45 -- Starting angle for vertical rotation
local verticalSensitivity = 0.01 -- Sensitivity for vertical movement
local horizontalSensitivity = 0.01 -- Sensitivity for horizontal movement
local zoomSensitivity = 100 -- Sensitivity for zooming
-- Function to update camera position based on drag offset
local function updateCameraPosition(dragOffset)
-- Update the rotation angles with sensitivity
horizontalRotation = horizontalRotation - (dragOffset.X * horizontalSensitivity)
verticalRotation = verticalRotation + (dragOffset.Y * verticalSensitivity)
-- Clamp vertical rotation to avoid reaching extreme angles
verticalRotation = math.clamp(verticalRotation, -math.pi / 2 + 0.15, math.pi / 2 - 0.15)
-- Calculate the new camera position based on spherical coordinates
local x = distanceFromPlanet * math.cos(verticalRotation) * math.sin(horizontalRotation)
local y = distanceFromPlanet * math.sin(verticalRotation)
local z = distanceFromPlanet * math.cos(verticalRotation) * math.cos(horizontalRotation)
-- Set the camera's CFrame
camera.CFrame = CFrame.new(Vector3.new(x, y, z) + planetsFolder.Planet1.Position, planetsFolder.Planet1.Position)
end
-- Mouse input handling using UI DragDetector
local userInputService = game:GetService("UserInputService")
dragger.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
dragging = true
lastMousePosition = userInputService:GetMouseLocation() -- Get initial mouse position
end
end)
dragger.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
dragging = false
dragger.Position = originalPosition -- Reset dragger position when drag ends
end
end)
userInputService.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseWheel then
distanceFromPlanet = distanceFromPlanet - (input.Position.Z * zoomSensitivity)
distanceFromPlanet = math.clamp(distanceFromPlanet, 1000, 20000)
end
end)
game:GetService("RunService").RenderStepped:Connect(function()
if dragging then
local mousePosition = userInputService:GetMouseLocation()
local dragOffset = mousePosition - lastMousePosition
lastMousePosition = mousePosition
updateCameraPosition(dragOffset)
end
updateCameraPosition(Vector2.new(0, 0))
for planetName, imageButton in pairs(imageButtons) do
local planet = planetsFolder:FindFirstChild(planetName)
if planet and (planet:IsA("Model") or planet:IsA("Part")) then
local positionToUse = planet:IsA("Model") and planet.PrimaryPart.Position or planet.Position
local screenPosition, onScreen = camera:WorldToScreenPoint(positionToUse)
print(planet.Name .. " screenPosition: " .. tostring(screenPosition) .. " onScreen: " .. tostring(onScreen))
if onScreen then
imageButton.Position = UDim2.new(0, screenPosition.X * 903, 0, screenPosition.Y * 648)
else
imageButton.Position = UDim2.new(1, 0, 1, 0)
end
end
end
end)
updateCameraPosition(Vector2.new(0, 0))