Roblox · Интерфейсы

Экран загрузки и главное меню

При входе — свой экран загрузки с полосой, потом главное меню на фоне карты: «Играть» и «Настройки». Пока меню открыто, персонаж стоит, а камера смотрит на мир с красивой точки.

Структура

Синим — что нужно создать.

ReplicatedFirst — загружается раньше всего
└─ LoadingScript (LocalScript)
   └─ LoadingGui (ScreenGui) — IgnoreGuiInset вкл., ResetOnSpawn выкл., DisplayOrder 100
      └─ Back (CanvasGroup) — Title, BarBack → Bar, Status
StarterGui
└─ MenuGui (ScreenGui) — ResetOnSpawn выкл., IgnoreGuiInset вкл.
   ├─ Menu (CanvasGroup) — Title, PlayButton, SettingsButton
   └─ MenuLocal (LocalScript)
Workspace
└─ MenuCamera (Part) — невидимая, смотрит на карту

Шаги

  1. ReplicatedFirst → LocalScript «LoadingScript». Внутри скрипта — ScreenGui «LoadingGui» (IgnoreGuiInset вкл., ResetOnSpawn выкл., DisplayOrder 100). ReplicatedFirst грузится первым, поэтому экран появляется сразу.
  2. В LoadingGui — CanvasGroup «Back» на весь экран: TextLabel «Title», Frame «BarBack» с Frame «Bar» (Size {0,0},{1,0}), TextLabel «Status».
  3. Скрипт убирает стандартный экран Roblox, ждёт game:IsLoaded() (и минимум 2 секунды) и плавно растворяет экран.
  4. StarterGui → ScreenGui «MenuGui» → CanvasGroup «Menu» на весь экран (чёрный, прозрачность 0.5): «Title», TextButton «PlayButton» и «SettingsButton». LocalScript «MenuLocal».
  5. Workspace → невидимая деталь «MenuCamera» (Transparency 1, CanCollide и CanQuery выкл.). Передняя грань — куда смотрит камера меню.
  6. «Настройки» открывают окно из темы «Окно настроек». Если его нет — кнопка сама прячется.

Скрипты

LoadingScript

Где: ReplicatedFirst · LocalScript
Зачем: Экран загрузки.

-- игроки
local Players = game:GetService("Players")
-- загружается самым первым
local ReplicatedFirst = game:GetService("ReplicatedFirst")
-- сколько файлов ещё грузится
local ContentProvider = game:GetService("ContentProvider")
-- плавное исчезание
local TweenService = game:GetService("TweenService")
-- этот игрок
local player = Players.LocalPlayer
-- экран загрузки лежит внутри скрипта
local gui = script:WaitForChild("LoadingGui")
-- показываем хотя бы 2 секунды — без мелькания
local MIN_TIME = 2

-- показываем
gui.Parent = player:WaitForChild("PlayerGui")
-- убираем стандартный экран Roblox
ReplicatedFirst:RemoveDefaultLoadingScreen()
-- фон (CanvasGroup)
local back = gui:WaitForChild("Back")
-- полоса загрузки
local bar = back:WaitForChild("BarBack"):WaitForChild("Bar")
-- надпись
local status = back:WaitForChild("Status")
-- время начала
local start = os.clock()

-- пока игра грузится
while not game:IsLoaded() or os.clock() - start < MIN_TIME do
    -- до загрузки полоса не доходит до конца
    local k = math.clamp((os.clock() - start) / MIN_TIME, 0, game:IsLoaded() and 1 or 0.9)
    -- длина полосы
    bar.Size = UDim2.fromScale(k, 1)
    -- сколько осталось
    status.Text = "Загрузка… файлов в очереди: " .. ContentProvider.RequestQueueSize
    -- 10 раз в секунду
    task.wait(0.1)
-- конец цикла
end
-- полоса полная
bar.Size = UDim2.fromScale(1, 1)
-- надпись
status.Text = "Готово!"
-- исчезает
local fade = TweenService:Create(back, TweenInfo.new(0.6), {GroupTransparency = 1})
-- запускаем
fade:Play()
-- ждём
fade.Completed:Wait()
-- экран больше не нужен
gui:Destroy()

MenuLocal

Где: StarterGui → MenuGui · LocalScript
Зачем: Главное меню.

-- игроки
local Players = game:GetService("Players")
-- каждый кадр
local RunService = game:GetService("RunService")
-- плавное исчезание
local TweenService = game:GetService("TweenService")
-- этот игрок
local player = Players.LocalPlayer
-- камера
local camera = workspace.CurrentCamera
-- MenuGui
local gui = script.Parent
-- окно меню (CanvasGroup)
local menu = gui:WaitForChild("Menu")
-- «Играть»
local playButton = menu:WaitForChild("PlayButton")
-- «Настройки»
local settingsButton = menu:WaitForChild("SettingsButton")
-- деталь, откуда смотрит камера в меню
local menuCamera = workspace:FindFirstChild("MenuCamera")
-- управление персонажем
local controls = require(player:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule")):GetControls()
-- меню открыто
local inMenu = true

-- в меню персонаж не ходит
controls:Disable()
-- каждый кадр, пока меню
local follow = RunService.RenderStepped:Connect(function()
    -- есть точка обзора
    if menuCamera then
        -- камерой управляет скрипт
        camera.CameraType = Enum.CameraType.Scriptable
        -- смотрим с MenuCamera
        camera.CFrame = menuCamera.CFrame
    -- конец проверки
    end
-- конец функции
end)

-- «Играть»
playButton.Activated:Connect(function()
    -- уже играем
    if not inMenu then return end
    -- меню закрывается
    inMenu = false
    -- камера свободна
    follow:Disconnect()
    -- обычная камера за персонажем
    camera.CameraType = Enum.CameraType.Custom
    -- можно ходить
    controls:Enable()
    -- меню тает
    local fade = TweenService:Create(menu, TweenInfo.new(0.5), {GroupTransparency = 1})
    -- запускаем
    fade:Play()
    -- ждём
    fade.Completed:Wait()
    -- прячем
    gui.Enabled = false
-- конец функции
end)
-- «Настройки»
settingsButton.Activated:Connect(function()
    -- окно настроек (тема «Окно настроек»)
    local settings = player.PlayerGui:FindFirstChild("SettingsGui")
    -- открыть / закрыть
    if settings then settings.Window.Visible = not settings.Window.Visible end
-- конец функции
end)
-- нет окна настроек — кнопку прячем
settingsButton.Visible = player.PlayerGui:WaitForChild("SettingsGui", 3) ~= nil

Проверка

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

Собрать загрузку и меню одной командой