Roblox · Песочница · урок 8

Сон

Ночью ложишься на кровать — «Лечь спать?»: «Да» — экран темнеет, наступает утро, здоровье полное. Прыжок — встать.

Структура

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

Workspace
└─ Bed (Model) — кровать в доме
   └─ BedPart (Part) — невидимая, Anchored, CanCollide выкл.; ProximityPrompt «Лечь»
      └─ BedScript (Script)
ReplicatedStorage
└─ SleepEvent, TimeEvent (RemoteEvent)
ServerScriptService
└─ DayNight (Script) — смена дня и ночи
StarterGui
└─ SleepGui (ScreenGui) — ResetOnSpawn выкл.
   └─ SleepFrame (Frame) — SleepText, Yes, No; SleepLocal

Шаги

  1. Зачем сон: пропустить ночь, восстановить силы, сохраниться, дать подсказку во сне, сменить реальность.
  2. Кровать: модель, на ней невидимая «BedPart» там, где должен лежать персонаж (Anchored, CanCollide выкл.). В BedPart — ProximityPrompt (ActionText «Лечь») и Script «BedScript».
  3. PlatformStand = true — персонаж «лежит» и не встаёт сам; прыжок — встать. В методичке ложились касанием, и каждое касание запускало бесконечный цикл проверки времени.
  4. DayNight: ClockTime +0.05 в секунду — сутки за 8 минут. Ночь — с 20 до 6.
  5. SleepGui → SleepFrame: TextLabel «SleepText» («Лечь спать?»), TextButton «Yes» и «No», LocalScript «SleepLocal».
  6. Затемнение — свой ColorCorrectionEffect: Brightness до −1 и обратно. В методичке эффект не включался, если в Lighting уже был другой ColorCorrection.
  7. Сервер ставит утро, только если игрок действительно лежит на этой кровати и сейчас ночь.

Скрипты

DayNight

Где: ServerScriptService · Script
Зачем: Смена дня и ночи.

-- освещение
local Lighting = game:GetService("Lighting")
-- часов за секунду: сутки — 8 минут
local STEP = 0.05

-- бесконечно
while true do
    -- секунда
    task.wait(1)
    -- время идёт, после 24 — снова 0
    Lighting.ClockTime = (Lighting.ClockTime + STEP) % 24
-- конец цикла
end

BedScript

Где: Workspace → Bed → BedPart · Script
Зачем: Лечь, встать, утро.

-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- время суток
local Lighting = game:GetService("Lighting")
-- BedPart — где лежит персонаж
local part = script.Parent
-- «Лечь»
local prompt = part:WaitForChild("ProximityPrompt")
-- спросить игрока «Спать?»
local sleepEvent = RS:WaitForChild("SleepEvent")
-- игрок согласился
local timeEvent = RS:WaitForChild("TimeEvent")
-- кто лежит
local current = nil
-- сварка с кроватью
local weld = nil
-- подписка «прыжок — встать»
local jumpConnection = nil

-- сейчас ночь?
local function IsNight()
    -- с 20 до 6
    return Lighting.ClockTime >= 20 or Lighting.ClockTime < 6
-- конец функции
end

-- встать с кровати
local function StandUp()
    -- никто не лежит
    if not current then return end
    -- отвариваем
    if weld then weld:Destroy() end
    -- отписываемся
    if jumpConnection then jumpConnection:Disconnect() end
    -- ничего нет
    weld, jumpConnection = nil, nil
    -- Humanoid
    local humanoid = current:FindFirstChildOfClass("Humanoid")
    -- снова управляем
    if humanoid then humanoid.PlatformStand = false end
    -- ставим рядом с кроватью
    if current.Parent then current:PivotTo(part.CFrame + Vector3.new(0, 4, 0)) end
    -- кровать свободна
    current = nil
    -- можно лечь снова
    prompt.Enabled = true
-- конец функции
end

-- игрок нажал «Лечь»
prompt.Triggered:Connect(function(player)
    -- персонаж
    local character = player.Character
    -- Humanoid
    local humanoid = character and character:FindFirstChildOfClass("Humanoid")
    -- центр
    local root = character and character:FindFirstChild("HumanoidRootPart")
    -- прошлый игрок вышел из игры — кровать свободна
    if current and not current.Parent then StandUp() end
    -- занято или погиб
    if current or not humanoid or not root or humanoid.Health <= 0 then return end
    -- лежит он
    current = character
    -- второй не ляжет
    prompt.Enabled = false
    -- персонаж «лежит», а не стоит
    humanoid.PlatformStand = true
    -- лёжа на кровати
    root.CFrame = part.CFrame * CFrame.Angles(math.rad(90), 0, 0)
    -- приварим к кровати
    weld = Instance.new("WeldConstraint")
    -- кровать
    weld.Part0 = part
    -- персонаж
    weld.Part1 = root
    -- в кровать
    weld.Parent = part
    -- нажал прыжок
    jumpConnection = humanoid:GetPropertyChangedSignal("Jump"):Connect(function()
        -- встаёт
        if humanoid.Jump then StandUp() end
    -- конец функции
    end)
    -- погиб в кровати — кровать освобождается
    humanoid.Died:Once(function() if current == character then StandUp() end end)
    -- ночью спросим «Спать?»
    if IsNight() then sleepEvent:FireClient(player) end
-- конец функции
end)

-- игрок выбрал «Да»
timeEvent.OnServerEvent:Connect(function(player)
    -- лежит не он или уже не ночь
    if current ~= player.Character or not IsNight() then return end
    -- утро
    Lighting.ClockTime = 7
    -- Humanoid
    local humanoid = current:FindFirstChildOfClass("Humanoid")
    -- выспался — здоровье полное
    if humanoid then humanoid.Health = humanoid.MaxHealth end
-- конец функции
end)

SleepLocal

Где: StarterGui → SleepGui → SleepFrame · LocalScript
Зачем: «Лечь спать?» и затемнение.

-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- плавное затемнение
local TS = game:GetService("TweenService")
-- эффекты экрана
local Lighting = game:GetService("Lighting")
-- окно «Лечь спать?»
local frame = script.Parent
-- кровать спросила
local sleepEvent = RS:WaitForChild("SleepEvent")
-- сказать серверу «Да»
local timeEvent = RS:WaitForChild("TimeEvent")
-- сначала скрыто
frame.Visible = false

-- лёг ночью
sleepEvent.OnClientEvent:Connect(function()
    -- спрашиваем
    frame.Visible = true
-- конец функции
end)
-- «Да» — подписка одна
frame:WaitForChild("Yes").MouseButton1Click:Connect(function()
    -- прячем окно
    frame.Visible = false
    -- свой эффект — даже если в Lighting уже есть другой
    local fade = Instance.new("ColorCorrectionEffect")
    -- имя
    fade.Name = "SleepFade"
    -- только у этого игрока
    fade.Parent = Lighting
    -- экран темнеет
    local dark = TS:Create(fade, TweenInfo.new(2), {Brightness = -1})
    -- засыпаем
    dark:Play()
    -- ждём
    dark.Completed:Wait()
    -- сервер ставит утро
    timeEvent:FireServer()
    -- спим
    task.wait(1)
    -- светлеет
    local light = TS:Create(fade, TweenInfo.new(2), {Brightness = 0})
    -- просыпаемся
    light:Play()
    -- ждём
    light.Completed:Wait()
    -- эффект больше не нужен
    fade:Destroy()
-- конец функции
end)
-- «Нет»
frame:WaitForChild("No").MouseButton1Click:Connect(function() frame.Visible = false end)

Проверка

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