Roblox · Интерфейсы
На экране — значок с расстоянием до цели. Цель видна — значок над ней; за краем экрана или за спиной — стрелка у края показывает, куда повернуть.
Синим — что нужно создать.
Workspace └─ Waypoints (Folder) └─ 1, 2, 3 (Part) — точки маршрута ServerScriptService └─ QuestTargetServer (Script) Players → игрок — создаёт скрипт └─ QuestTarget (ObjectValue) — текущая цель StarterGui └─ ArrowGui (ScreenGui) — ResetOnSpawn выкл., IgnoreGuiInset вкл. ├─ Marker (Frame) — AnchorPoint 0.5, 0.5; Size 70 × 70 px │ ├─ Arrow (TextLabel) — «▲» │ └─ Distance (TextLabel) └─ ArrowLocal (LocalScript)
Где: ServerScriptService · Script
Зачем: Цель и маршрут по точкам.
-- игроки
local Players = game:GetService("Players")
-- точки маршрута 1, 2, 3…
local points = workspace:WaitForChild("Waypoints")
-- точка по номеру
local function Point(number)
-- nil, если такой нет
return points:FindFirstChild(tostring(number))
-- конец функции
end
-- игрок зашёл
local function Setup(player)
-- текущая цель игрока
local target = Instance.new("ObjectValue")
-- имя — его читает стрелка
target.Name = "QuestTarget"
-- первая точка
target.Value = Point(1)
-- в игрока — клиент видит
target.Parent = player
-- конец функции
end
-- новые игроки
Players.PlayerAdded:Connect(Setup)
-- кто зашёл раньше скрипта
for _, player in ipairs(Players:GetPlayers()) do Setup(player) end
-- каждая точка
for _, point in ipairs(points:GetChildren()) do
-- касание
point.Touched:Connect(function(hit)
-- игрок?
local player = Players:GetPlayerFromCharacter(hit.Parent)
-- его цель
local target = player and player:FindFirstChild("QuestTarget")
-- это не его текущая цель
if not target or target.Value ~= point then return end
-- следующая точка; после последней — nil, стрелка пропадёт
target.Value = Point(tonumber(point.Name) + 1)
-- конец функции
end)
-- конец перебора
endГде: StarterGui → ArrowGui · LocalScript
Зачем: Значок и стрелка.
-- игроки
local Players = game:GetService("Players")
-- каждый кадр
local RunService = game:GetService("RunService")
-- этот игрок
local player = Players.LocalPlayer
-- камера
local camera = workspace.CurrentCamera
-- значок цели
local marker = script.Parent:WaitForChild("Marker")
-- стрелка «▲»
local arrow = marker:WaitForChild("Arrow")
-- «25 м»
local distanceLabel = marker:WaitForChild("Distance")
-- ObjectValue: на что указывать
local target = player:WaitForChild("QuestTarget")
-- отступ от края экрана, px
local EDGE = 50
-- каждый кадр
RunService.RenderStepped:Connect(function()
-- цель
local goal = target.Value
-- персонаж
local character = player.Character
-- его центр
local root = character and character:FindFirstChild("HumanoidRootPart")
-- цели нет
if not goal or not root then
-- прячем
marker.Visible = false
-- выходим
return
-- конец проверки
end
-- где цель (деталь или модель)
local position = goal:IsA("Model") and goal:GetPivot().Position or goal.Position
-- показываем
marker.Visible = true
-- расстояние в studs
distanceLabel.Text = math.floor((position - root.Position).Magnitude) .. " м"
-- где цель на экране
local point, onScreen = camera:WorldToViewportPoint(position)
-- центр экрана
local center = camera.ViewportSize / 2
-- точка на экране
local screen = Vector2.new(point.X, point.Y)
-- цель за спиной — отражаем
if point.Z < 0 then screen = center - (screen - center) end
-- цель видна
if onScreen then
-- значок прямо на ней
marker.Position = UDim2.fromOffset(screen.X, screen.Y)
-- стрелка вниз — «вот здесь»
arrow.Rotation = 180
-- цель за краем экрана
else
-- направление от центра
local dir = screen - center
-- на всякий случай — вверх
if dir.Magnitude < 1 then dir = Vector2.new(0, -1) end
-- длина 1
dir = dir.Unit
-- до края с отступом
local half = center - Vector2.new(EDGE, EDGE)
-- сколько шагнуть до края
local k = math.min(half.X / math.max(math.abs(dir.X), 1e-6), half.Y / math.max(math.abs(dir.Y), 1e-6))
-- точка у края
local pos = center + dir * k
-- значок у края
marker.Position = UDim2.fromOffset(pos.X, pos.Y)
-- стрелка смотрит в сторону цели
arrow.Rotation = math.deg(math.atan2(dir.Y, dir.X)) + 90
-- конец проверки
end
-- конец функции
end)Запусти Play (или Run) и убедись: