Roblox · RPG · урок 3

Тайники и мини-карта

Исследование мира: тайники с сундуками и мини-карта в углу экрана, на которой виден ты и всё вокруг.

Структура

Синим — что добавляем на этом уроке.

Workspace
└─ MapFolder (Folder)
   ├─ Chest (Model) — сундук в тайнике
   │  └─ Highlight (Highlight) — подсветка — видно, что можно взять
   └─ Sign (Part) — табличка у тайника
StarterGui
└─ MiniMapGui (ScreenGui) — ResetOnSpawn выкл.
   ├─ MapFrame (ViewportFrame) — квадрат в углу
   │  ├─ UIAspectRatioConstraint (UIAspectRatioConstraint) — всегда квадрат
   │  └─ PlayerArrow (ImageLabel) — стрелка, смотрит вверх
   └─ MapScript (LocalScript)

Шаги

  1. Что мотивирует исследовать: валюта, коллекционные предметы, оружие, знания о мире.
  2. Правила: место награды отличается от окружения, объект взаимодействия подсвечен, все такие объекты одинаковые.
  3. Тайники — в пещерах, на деревьях, у озёр. Рядом табличка-указатель. Внутри сундук — одна модель на всю карту.
  4. Подсветка: в модель сундука — Highlight. DepthMode AlwaysOnTop — видно сквозь стены, Occluded — только напрямую. FillColor, FillTransparency, OutlineColor, OutlineTransparency.
  5. Мини-карта: StarterGui → ScreenGui «MiniMapGui» → ViewportFrame «MapFrame» (квадрат в углу, цвет фона = цвет земли: ландшафт в окне не виден). Внутрь UIAspectRatioConstraint и ImageLabel «PlayerArrow».
  6. Картинка стрелки: Toolbox → Images → «Arrow», ID — в Image. Стрелка должна смотреть вверх.
  7. LocalScript «MapScript» в MiniMapGui: копирует MapFolder в окно и держит над игроком камеру. Скрипты из копий удаляются.

Скрипты

MapScript

Где: StarterGui → MiniMapGui · LocalScript
Зачем: Мини-карта со стрелкой игрока.

-- игроки
local Players = game:GetService("Players")
-- каждый кадр
local RunService = game:GetService("RunService")
-- этот игрок
local player = Players.LocalPlayer
-- всё, что видно на мини-карте
local mapFolder = workspace:WaitForChild("MapFolder")
-- ViewportFrame — окно с 3D-копией карты
local mapFrame = script.Parent:WaitForChild("MapFrame")
-- стрелка игрока
local arrow = mapFrame:WaitForChild("PlayerArrow")
-- с какой высоты смотрит камера карты
local HEIGHT = 2500

-- своя камера для окна карты
local camera = Instance.new("Camera")
-- узкий угол — почти без перспективы, как план
camera.FieldOfView = 1
-- лежит в самом окне
camera.Parent = mapFrame
-- окно смотрит через неё
mapFrame.CurrentCamera = camera

-- каждый объект карты
for _, obj in ipairs(mapFolder:GetChildren()) do
    -- копия (некоторые объекты копироваться не умеют)
    local ok, copy = pcall(function() return obj:Clone() end)
    -- получилось
    if ok and copy then
        -- всё внутри копии
        for _, inner in ipairs(copy:GetDescendants()) do
            -- скрипты убираем — иначе локальные заработают
            if inner:IsA("LuaSourceContainer") then inner:Destroy() end
        -- конец перебора
        end
        -- в окно карты
        copy.Parent = mapFrame
    -- конец проверки
    end
-- конец перебора
end

-- каждый кадр
RunService.RenderStepped:Connect(function()
    -- персонаж (после смерти — новый)
    local character = player.Character
    -- его центр
    local root = character and character:FindFirstChild("HumanoidRootPart")
    -- персонажа ещё нет
    if not root then return end
    -- сверху вниз; «верх» карты — север
    camera.CFrame = CFrame.lookAt(root.Position + Vector3.new(0, HEIGHT, 0), root.Position, Vector3.new(0, 0, -1))
    -- стрелка поворачивается вместе с персонажем
    arrow.Rotation = -root.Orientation.Y
-- конец функции
end)

Проверка

Запусти Play (или Run) и убедись: