Roblox · Движение
Вода из ландшафта: плавать Roblox умеет сам. Добавляем воздух: голова под водой — внизу экрана голубая полоска тает, кончилась — персонаж получает урон. Вынырнул — воздух быстро восстанавливается.
Синим — что нужно создать.
Workspace └─ Terrain — вода — Terrain Editor → Fill / Paint → Water StarterPlayer └─ StarterCharacterScripts └─ AirServer (Script) — серверный: воздух и урон StarterGui └─ AirGui (ScreenGui) — ResetOnSpawn выкл. ├─ Frame (Frame) — полоска внизу, Visible выкл. │ └─ Bar (Frame) — голубая, Size 1, 0, 1, 0 └─ AirLocal (LocalScript)
Где: StarterPlayer → StarterCharacterScripts · Script
Зачем: Воздух под водой и урон от удушья.
-- персонаж (скрипт в StarterCharacterScripts)
local character = script.Parent
-- его Humanoid
local humanoid = character:WaitForChild("Humanoid")
-- голова — под водой ли она
local head = character:WaitForChild("Head")
-- ландшафт с водой
local terrain = workspace.Terrain
-- секунд под водой без вреда
local MAX_AIR = 10
-- урон в секунду, когда воздух кончился
local DAMAGE = 10
-- максимум — для полоски
humanoid:SetAttribute("MaxAir", MAX_AIR)
-- воздух полный
humanoid:SetAttribute("Air", MAX_AIR)
-- голова в воде?
local function HeadUnderWater()
-- где голова
local p = head.Position
-- угол клетки ландшафта 4 × 4 × 4
local low = Vector3.new(math.floor(p.X / 4) * 4, math.floor(p.Y / 4) * 4, math.floor(p.Z / 4) * 4)
-- читаем одну клетку
local materials, occupancies = terrain:ReadVoxels(Region3.new(low, low + Vector3.new(4, 4, 4)), 4)
-- вода и её больше половины
return materials[1][1][1] == Enum.Material.Water and occupancies[1][1][1] > 0.5
-- конец функции
end
-- пока жив
while humanoid.Health > 0 do
-- 4 раза в секунду
task.wait(0.25)
-- воздух сейчас
local air = humanoid:GetAttribute("Air")
-- под водой
if HeadUnderWater() then
-- воздух тратится
air = math.max(air - 0.25, 0)
-- кончился — урон
if air == 0 then humanoid:TakeDamage(DAMAGE * 0.25) end
-- над водой
else
-- быстро восстанавливается
air = math.min(air + 1, MAX_AIR)
-- конец проверки
end
-- записываем — полоска у игрока обновится
humanoid:SetAttribute("Air", air)
-- конец цикла
endГде: StarterGui → AirGui · LocalScript
Зачем: Полоска воздуха.
-- этот игрок
local player = game.Players.LocalPlayer
-- AirGui
local gui = script.Parent
-- полоска
local frame = gui:WaitForChild("Frame")
-- воздух
local bar = frame:WaitForChild("Bar")
-- подписка на атрибут
local connection = nil
-- новый персонаж
local function Watch(character)
-- его Humanoid
local humanoid = character:WaitForChild("Humanoid")
-- старая подписка
if connection then connection:Disconnect() end
-- обновить полоску
local function Show()
-- воздух
local air = humanoid:GetAttribute("Air") or 10
-- максимум
local max = humanoid:GetAttribute("MaxAir") or 10
-- длина полосы
bar.Size = UDim2.fromScale(air / max, 1)
-- полный воздух — полоска не нужна
frame.Visible = air < max
-- конец функции
end
-- сразу
Show()
-- воздух изменился
connection = humanoid:GetAttributeChangedSignal("Air"):Connect(Show)
-- конец функции
end
-- каждый персонаж
player.CharacterAdded:Connect(Watch)
-- уже появился
if player.Character then Watch(player.Character) endЗапусти Play (или Run) и убедись: