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

Всплывающие цифры урона

Ударил моба — над ним взлетает красное «-25» и тает. Лечение — зелёное «+20». Работает для всех мобов и других игроков, без изменений в оружии.

Структура

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

StarterPlayer → StarterPlayerScripts
└─ DamageNumbersLocal (LocalScript)
Workspace
└─ Dummy (Model) — манекен для проверки
   ├─ ClickDetector (ClickDetector)
   └─ ClickDamage (Script)

Шаги

  1. StarterPlayer → StarterPlayerScripts → LocalScript «DamageNumbersLocal». Интерфейс создаёт сам скрипт.
  2. Скрипт следит за здоровьем всех Humanoid в Workspace: уменьшилось — красная цифра, выросло на 5 и больше — зелёная. Мелкую регенерацию не показываем, чтобы не мельтешило.
  3. Цифры видит каждый игрок у себя — серверу ничего делать не нужно, а оружие менять не надо.
  4. Свои цифры игрок не видит: для себя — полоска здоровья и вспышка (соседние темы).
  5. Для проверки — манекен «Dummy» с ClickDetector и скриптом «ClickDamage»: клик отнимает 15.

Скрипты

DamageNumbersLocal

Где: StarterPlayer → StarterPlayerScripts · LocalScript
Зачем: Цифры над всеми, кто получил урон.

-- игроки
local Players = game:GetService("Players")
-- плавный взлёт
local TweenService = game:GetService("TweenService")
-- удаляет через время
local Debris = game:GetService("Debris")
-- этот игрок
local player = Players.LocalPlayer
-- мелкое лечение (регенерацию) не показываем
local MIN_HEAL = 5
-- урон — красный
local DAMAGE_COLOR = Color3.fromRGB(255, 80, 80)
-- лечение — зелёный
local HEAL_COLOR = Color3.fromRGB(90, 230, 110)

-- цифра над деталью
local function Popup(part, amount)
    -- надпись в мире
    local gui = Instance.new("BillboardGui")
    -- 3 × 1.5 studs
    gui.Size = UDim2.fromScale(3, 1.5)
    -- над головой, чуть вбок — цифры не слипаются
    gui.StudsOffset = Vector3.new(math.random(-10, 10) / 10, 2.5, 0)
    -- видно сквозь стены
    gui.AlwaysOnTop = true
    -- дальше не показываем
    gui.MaxDistance = 80
    -- над чем
    gui.Adornee = part
    -- сама цифра
    local label = Instance.new("TextLabel")
    -- во всю надпись
    label.Size = UDim2.fromScale(1, 1)
    -- без фона
    label.BackgroundTransparency = 1
    -- жирный шрифт
    label.Font = Enum.Font.GothamBlack
    -- по размеру
    label.TextScaled = true
    -- чёрная обводка
    label.TextStrokeTransparency = 0
    -- «-15» или «+20»
    label.Text = (amount < 0 and "-" or "+") .. math.floor(math.abs(amount) + 0.5)
    -- цвет
    label.TextColor3 = amount < 0 and DAMAGE_COLOR or HEAL_COLOR
    -- в надпись
    label.Parent = gui
    -- только у этого игрока
    gui.Parent = part
    -- 0.8 секунды, с замедлением
    local info = TweenInfo.new(0.8, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
    -- взлетает
    TweenService:Create(gui, info, {StudsOffset = gui.StudsOffset + Vector3.new(0, 2, 0)}):Play()
    -- и тает
    TweenService:Create(label, info, {TextTransparency = 1, TextStrokeTransparency = 1}):Play()
    -- потом удаляется
    Debris:AddItem(gui, 0.9)
-- конец функции
end

-- следим за здоровьем одного персонажа
local function Watch(humanoid)
    -- модель
    local model = humanoid.Parent
    -- Humanoid не в модели
    if not model or not model:IsA("Model") then return end
    -- здоровье до изменения
    local last = humanoid.Health
    -- здоровье изменилось
    humanoid.HealthChanged:Connect(function(health)
        -- на сколько
        local diff = health - last
        -- запоминаем
        last = health
        -- свои цифры не показываем — у себя видно полоску
        if model == player.Character then return end
        -- почти ничего или мелкое лечение
        if diff > -0.5 and diff < MIN_HEAL then return end
        -- над чем показать
        local part = model:FindFirstChild("Head") or model:FindFirstChild("HumanoidRootPart")
        -- цифра
        if part then Popup(part, diff) end
    -- конец функции
    end)
-- конец функции
end

-- персонажи, которые уже есть
for _, obj in ipairs(workspace:GetDescendants()) do
    -- следим
    if obj:IsA("Humanoid") then Watch(obj) end
-- конец перебора
end
-- появился новый объект
workspace.DescendantAdded:Connect(function(obj)
    -- моб или игрок — следим
    if obj:IsA("Humanoid") then Watch(obj) end
-- конец функции
end)

ClickDamage

Где: Workspace → Dummy · Script
Зачем: Манекен для проверки.

-- манекен для проверки
local dummy = script.Parent
-- его здоровье
local humanoid = dummy:WaitForChild("Humanoid")
-- клик мышью
local clicker = dummy:WaitForChild("ClickDetector")

-- клик по манекену
clicker.MouseClick:Connect(function()
    -- −15 здоровья
    humanoid:TakeDamage(15)
-- конец функции
end)
-- медленно лечится
while true do
    -- раз в секунду
    task.wait(1)
    -- +2, пока жив
    if humanoid.Health > 0 then humanoid.Health = math.min(humanoid.Health + 2, humanoid.MaxHealth) end
-- конец цикла
end

Проверка

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

Собрать цифры урона одной командой