Практикум — королевская битва на Roblox
Roblox
Продолжение маршрута после обби: цикл лобби → отсчёт → бой → победитель, оружие с Raycast на клиенте для визуала и повторной проверкой на сервере. API — workspace:Raycast, Luau и task.*.
Что вы освоите
| Тема | Навык |
|---|---|
| Игровой цикл раундов | Lobby / Intermission / Combat / Winner |
| Минимум игроков | MIN_PLAYERS, ожидание в while |
| Таблица участников | competitors фиксируется на старт раунда |
| Конфиг оружия | ModuleScript Settings в Tool |
| Raycast | Клиент стреляет лучом; сервер сверяет угол и дистанцию |
| Headshot | Множитель урона по Head |
| Локальная репликация | Replicate RemoteEvent — трассер и звук |
Структура проекта
ServerScriptService
├── ServerHandler
│ ├── Data
│ ├── GameRunner
│ └── Weapons
ReplicatedStorage
├── Remotes
│ ├── Hit (RemoteEvent — заявка о попадании)
│ └── Replicate (RemoteEvent — VFX для всех)
├── Tools
│ └── Blaster (Tool + ModuleScript Settings + LocalScript ToolHandler)
Workspace
└── Effects (папка для временных Part трассеров)
StarterGui
└── RoundHUD (фаза, таймер)
Модуль GameRunner
Data для BR — те же Coins / Wins / Kills, что в обби; ключ DataStore смените, чтобы не смешивать тестовые данные.
Конфиг оружия
Tool/Settings (ModuleScript):
| Поле | Смысл |
|---|---|
rateOfFire |
Выстрелов в минуту; пауза 60 / rateOfFire |
range |
Длина луча в студах |
fireMode |
AUTO — цикл при зажатой кнопке |
Клиент — ToolHandler и Raycast
Replicate.OnClientEvent на всех клиентах создаёт короткий Part-трассер в workspace.Effects и удаляет через Debris.
Сервер — verifyHit и урон
Клиент присылает hit, origin, direction, relCFrame. Сервер не доверяет hit слепо:
Подключение:
Hit.OnServerEvent:Connect(function(player, tool, hit, direction, origin, relCFrame)
local settings = require(tool:WaitForChild("Settings"))
if not Weapons.verifyHit(player, tool, hit, direction, origin, relCFrame, settings) then
return
end
Weapons.applyDamage(player, hit, settings)
end)
В продакшене часто делают второй workspace:Raycast на сервере из origin по direction и сравнивают цель с ответом клиента. Это дороже по CPU, но устойчивее к подмене hit.
Локальная репликация VFX
| Что | Где |
|---|---|
| Трассер, дым, звук выстрела | Клиент стрелка + Replicate для остальных |
TakeDamage |
Только сервер |
| UI попадания | FireClient жертве после applyDamage |
Подробнее о репликации — Разработка на Roblox.
HUD раунда
RoundStatus.OnClientEvent обновляет TextLabel:
RoundStatus.OnClientEvent:Connect(function(phase: string, seconds: number)
if phase == "Intermission" then
label.Text = "Старт через " .. seconds
elseif phase == "Combat" then
label.Text = "Бой!"
elseif phase == "Winner" then
label.Text = "Победитель определён"
end
end)
Тестирование
| Сценарий | Ожидание |
|---|---|
| 1 игрок | Раунд ждёт MIN_PLAYERS |
| 2 клиента | Урон только через сервер; убийство засчитывается |
| Выход mid-round | competitors не ломает подсчёт живых |
| Headshot | Урон x headshotMultiplier только при hit.Name == "Head" |
Чек-лист
-
GameRunnerпроходит полный цикл Waiting → Combat → Winner -
Settingsв Tool,Debounceна Tool - Клиент использует
RaycastParams, не устаревшийFindPartOnRay -
verifyHitотсекает неверный угол и дистанцию - Урон и Kills только на сервере
- VFX через
Replicate, без локальногоTakeDamage