Единый контроллер: скорость, прыжок и размер
Шесть площадок меняют характеристики персонажа без взаимного сброса бонусов.
Площадки дают временные бонусы: ускорение, замедление, высокий прыжок, уменьшение и увеличение. Эффекты складываются и корректно исчезают.
1. Подготовьте объект
Где разместить: ModuleScript и Script в ServerScriptService; площадки в Workspace.
ServerScriptService
StatsController (ModuleScript)
StatsPadsServer (Script)
Workspace
StatsPads (Folder)
SpeedPad (Part)
SlowPad (Part)
JumpPad (Part)
SmallPad (Part)
BigPad (Part)
ResetPad (Part)- Создайте в ServerScriptService ModuleScript с точным именем StatsController. Замените его содержимое первым блоком кода.
- Рядом создайте обычный Script StatsPadsServer. Вставьте второй блок.
- В Workspace создайте Folder StatsPads и шесть Anchored Part с именами из схемы. Включите CanTouch.
- В Game Settings → Avatar выберите R15 для изменения размера. На R6 будут работать скорость и прыжок, но не масштабирование.
- Запустите Play. Наступите на SpeedPad, затем JumpPad: оба эффекта действуют одновременно. Через 10 секунд они исчезнут. ResetPad отменяет их сразу.
- В режиме Test → Start проверьте двух игроков: характеристики должны быть независимыми.
- Не добавляйте старые скрипты, напрямую меняющие WalkSpeed, JumpPower или ScaleTo, в ту же тестовую карту.
Это пути для скриптов из блоков кода ниже. Остальные объекты создайте по инструкции.
└── ServerScriptService
├── StatsController (ModuleScript)
└── StatsPadsServer (Script)2. Вставьте код
-- ModuleScript: ServerScriptService/StatsController
-- Одна серверная система для скорости, прыжка и масштаба R15.
local Players = game:GetService("Players")
local Controller = {}
local states = {}
local function recalculate(player)
local state = states[player]
if not state or player.Character ~= state.character then return end
local humanoid = state.character:FindFirstChildOfClass("Humanoid")
if not humanoid or humanoid.Health <= 0 then return end
local speed, jump, size = 1, 1, 1
for _, effect in pairs(state.effects) do
speed *= effect.speed
jump *= effect.jump
size *= effect.size
end
humanoid.UseJumpPower = true
humanoid.WalkSpeed = math.clamp(state.baseSpeed * speed, 8, 60)
humanoid.JumpPower = math.clamp(state.baseJump * jump, 25, 110)
if humanoid.RigType == Enum.HumanoidRigType.R15 then
local targetScale = math.clamp(state.baseScale * size, 0.65, 1.65)
if math.abs(state.character:GetScale() - targetScale) > 0.01 then
state.character:ScaleTo(targetScale)
end
end
end
function Controller.Apply(player, effectName, values, duration)
local state = states[player]
if not state or type(effectName) ~= "string" or type(values) ~= "table" then
return false
end
-- Не списываем монеты за эффект, если персонаж ещё не готов после возрождения.
if state.character ~= player.Character then return false end
local humanoid = state.character:FindFirstChildOfClass("Humanoid")
if not humanoid or humanoid.Health <= 0 then return false end
local token = {}
state.effects[effectName] = {
speed = math.clamp(tonumber(values.speed) or 1, 0.5, 3),
jump = math.clamp(tonumber(values.jump) or 1, 0.5, 3),
size = math.clamp(tonumber(values.size) or 1, 0.5, 2),
token = token,
}
recalculate(player)
if type(duration) == "number" and duration > 0 then
task.delay(math.min(duration, 300), function()
if states[player] == state then
local current = state.effects[effectName]
if current and current.token == token then
state.effects[effectName] = nil
recalculate(player)
end
end
end)
end
return true
end
function Controller.Remove(player, effectName)
local state = states[player]
if not state then return end
state.effects[effectName] = nil
recalculate(player)
end
function Controller.Clear(player)
local state = states[player]
if not state then return end
state.effects = {}
recalculate(player)
end
local function setupCharacter(player, character)
local humanoid = character:WaitForChild("Humanoid", 10)
if not humanoid or player.Character ~= character then return end
-- Короткая пауза: Roblox успевает создать основные части аватара.
task.wait(0.5)
if player.Character ~= character then return end
states[player] = {
character = character,
effects = {},
baseSpeed = humanoid.WalkSpeed,
baseJump = humanoid.JumpPower,
baseScale = character:GetScale(),
}
recalculate(player)
end
local function setupPlayer(player)
player.CharacterAdded:Connect(function(character)
task.spawn(setupCharacter, player, character)
end)
if player.Character then task.spawn(setupCharacter, player, player.Character) end
end
Players.PlayerAdded:Connect(setupPlayer)
Players.PlayerRemoving:Connect(function(player) states[player] = nil end)
for _, player in ipairs(Players:GetPlayers()) do setupPlayer(player) end
return Controller-- Script: ServerScriptService/StatsPadsServer
local Players = game:GetService("Players")
local Controller = require(script.Parent:WaitForChild("StatsController"))
local folder = workspace:WaitForChild("StatsPads")
local modes = {
SpeedPad = {speed = 1.7},
SlowPad = {speed = 0.65},
JumpPad = {jump = 1.6},
SmallPad = {size = 0.7},
BigPad = {size = 1.5},
}
local touched = {}
for _, pad in ipairs(folder:GetChildren()) do
if pad:IsA("BasePart") then
pad.Touched:Connect(function(hit)
local character = hit:FindFirstAncestorOfClass("Model")
local player = character and Players:GetPlayerFromCharacter(character)
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
if not player or not humanoid or humanoid.Health <= 0 then return end
touched[player] = touched[player] or {}
local now = os.clock()
if now - (touched[player][pad] or -100) < 1.5 then return end
touched[player][pad] = now
if pad.Name == "ResetPad" then
Controller.Clear(player)
elseif modes[pad.Name] then
Controller.Apply(player, pad.Name, modes[pad.Name], 10)
end
end)
end
end
Players.PlayerRemoving:Connect(function(player) touched[player] = nil end)3. Проверьте в игре
Нажмите Play в Roblox Studio и проверьте действие механики. Если механика не работает, откройте окно Output и проверьте тип скрипта, его расположение и названия объектов.
Когда проверите механику в Roblox Studio, отметьте практику как выполненную. Отметка хранится только в этом браузере, не в личном кабинете.
Добавляйте механики по одной и проверяйте окно Output. Не создавайте несколько одинаковых систем монет или интерфейсов; скрипты, меняющие WalkSpeed, прыжок или освещение, могут влиять друг на друга.
Измените длительность эффекта с 10 до 15 секунд.
Добавьте площадку SuperJumpPad с jump = 2.
Сделайте комнату испытаний с пятью разными усилениями и кнопкой сброса.
4. Проверьте себя
Почему несколько бонусов не сбрасывают друг друга при окончании?
Названия объектов должны совпадать с Explorer. ModuleScript возвращает Controller. Если размер не меняется, проверьте R15. Сначала проверьте Output. Не используйте одновременно старые скрипты, напрямую меняющие те же свойства. Для пользовательских аватаров масштабирование нужно проверять отдельно.