Roblox · Королевская битва · урок 11

Безопасное лобби, скин, стартовый экран и публикация

В лобби нельзя умереть: здоровье полное и невидимый щит. Всем — одинаковый скин. Стартовый экран с логотипом и именем автора. И публикация.

Структура

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

Workspace → Lobby
└─ SafeZone (Part) — невидимая коробка над всем лобби, CanCollide/CanQuery/CanTouch выкл.
ServerScriptService
└─ SafeZoneScript (Script)
StarterPlayer
└─ StarterCharacter (Model) — свой скин: Humanoid, HumanoidRootPart, Head; не Anchored
StarterGui
└─ StartGui (ScreenGui) — ResetOnSpawn выкл., IgnoreGuiInset вкл., DisplayOrder 10
   └─ StartFrame (Frame) — на весь экран, чёрный
      ├─ LogoFrame (Frame) — LogoImage (ImageLabel), LogoText (TextLabel) — прозрачные
      ├─ PresentedBy, Me (TextLabel) — TextTransparency 1
      └─ StartLocal (LocalScript)

Шаги

  1. Безопасная зона: невидимая коробка «SafeZone» над всем лобби. SafeZoneScript 5 раз в секунду: кто внутри — здоровье полное и невидимый ForceField (урон через TakeDamage его не пробивает); вышел — щит снимается.
  2. В методичке здоровье восстанавливалось всем и везде при любом изменении Humanoid — в бою тоже никто не умирал.
  3. Скин для всех: модель персонажа (Rig Builder или Toolbox) с Humanoid, HumanoidRootPart и Head, детали не Anchored. Назови «StarterCharacter» и положи в StarterPlayer — все игроки станут такими.
  4. Стартовый экран: StartGui → StartFrame на весь экран; внутри LogoFrame (LogoImage, LogoText), PresentedBy («Игру сделал»), Me (твоё имя). Всё прозрачное — StartLocal проявляет по очереди и открывает экран.
  5. Что делает игру «дороже»: яркая обложка (как превью на YouTube), стартовый экран с музыкой, звук у каждой кнопки, ветер, смена погоды и времени суток, титры с именами авторов.
  6. Публикация: File → Publish to Roblox; Game Settings → Permissions → Public; Security → API Services (для побед).

Скрипты

SafeZoneScript

Где: ServerScriptService · Script
Зачем: Бессмертие в лобби.

-- игроки
local Players = game:GetService("Players")
-- невидимая коробка над всем лобби
local zone = workspace:WaitForChild("Lobby"):WaitForChild("SafeZone")

-- точка в коробке?
local function Inside(position)
    -- координаты относительно коробки
    local p = zone.CFrame:PointToObjectSpace(position)
    -- внутри по всем трём осям
    return math.abs(p.X) <= zone.Size.X / 2 and math.abs(p.Y) <= zone.Size.Y / 2 and math.abs(p.Z) <= zone.Size.Z / 2
-- конец функции
end

-- постоянно
while true do
    -- 5 раз в секунду
    task.wait(0.2)
    -- каждый игрок
    for _, player in ipairs(Players:GetPlayers()) do
        -- персонаж
        local character = player.Character
        -- Humanoid
        local humanoid = character and character:FindFirstChildOfClass("Humanoid")
        -- центр
        local root = character and character:FindFirstChild("HumanoidRootPart")
        -- жив
        if humanoid and root and humanoid.Health > 0 then
            -- щит
            local shield = character:FindFirstChild("LobbyShield")
            -- в лобби
            if Inside(root.Position) then
                -- здоровье полное
                humanoid.Health = humanoid.MaxHealth
                -- щита нет
                if not shield then
                    -- ForceField: TakeDamage по нему не проходит
                    shield = Instance.new("ForceField")
                    -- имя
                    shield.Name = "LobbyShield"
                    -- без светящегося шара
                    shield.Visible = false
                    -- в персонажа
                    shield.Parent = character
                -- конец проверки
                end
            -- вышел из лобби
            elseif shield then
                -- щит снимаем
                shield:Destroy()
            -- конец проверки
            end
        -- конец проверки
        end
    -- конец перебора
    end
-- конец цикла
end

StartLocal

Где: StarterGui → StartGui → StartFrame · LocalScript
Зачем: Стартовый экран.

-- плавность
local TS = game:GetService("TweenService")
-- StartFrame на весь экран
local frame = script.Parent
-- логотип
local logoImage = frame:WaitForChild("LogoFrame"):WaitForChild("LogoImage")
-- название игры (в методичке то TextLabel, то LogoText)
local logoText = frame.LogoFrame:WaitForChild("LogoText")
-- «Игру сделал»
local presentedBy = frame:WaitForChild("PresentedBy")
-- имя разработчика
local me = frame:WaitForChild("Me")
-- плавно изменить прозрачность
local function Fade(object, property, value, seconds)
    -- анимация
    local tween = TS:Create(object, TweenInfo.new(seconds or 1), {[property] = value})
    -- запуск
    tween:Play()
    -- отдаём
    return tween
-- конец функции
end

-- экран закрыт
frame.Visible = true
-- чёрный
frame.BackgroundTransparency = 0
-- пауза
task.wait(1)
-- логотип проявляется
Fade(logoImage, "ImageTransparency", 0)
-- название
Fade(logoText, "TextTransparency", 0)
-- смотрим
task.wait(2.5)
-- исчезает
Fade(logoImage, "ImageTransparency", 1)
-- ждём
Fade(logoText, "TextTransparency", 1).Completed:Wait()
-- «Игру сделал»
Fade(presentedBy, "TextTransparency", 0)
-- смотрим
task.wait(2)
-- исчезает
Fade(presentedBy, "TextTransparency", 1).Completed:Wait()
-- имя
Fade(me, "TextTransparency", 0)
-- смотрим
task.wait(2)
-- исчезает
Fade(me, "TextTransparency", 1).Completed:Wait()
-- экран открывается
Fade(frame, "BackgroundTransparency", 1, 2).Completed:Wait()
-- больше не мешает кликам
frame.Visible = false

Проверка

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