Roblox · Гонки · урок 3
Рамки-чекпоинты по трассе: проезжать их нужно строго по порядку, пройденная рамка зеленеет только у тебя. После падения с трассы появляешься у последнего пройденного чекпоинта.
Синим — что добавляем на этом уроке.
Workspace └─ Checkpoints (Folder) ├─ 1 (Model) — имя — только номер; PrimaryPart = Trigger │ ├─ Trigger (Part) — рамка: Anchored, CanCollide выкл., полупрозрачная │ └─ Pillar1, Pillar2, … (Part) — украшения (столбы, арка) — по желанию └─ 2, 3, … (Model) — такие же, по порядку вдоль трассы ReplicatedStorage └─ CheckpointEvent (RemoteEvent) ServerScriptService └─ CheckpointsServer (Script) StarterPlayer └─ StarterPlayerScripts └─ CheckpointsLocal (LocalScript)
Где: ServerScriptService · Script
Зачем: Считает пройденные чекпоинты каждого игрока по порядку и возрождает у последнего.
-- папка с чекпоинтами-моделями 1, 2, 3…
local checkpoints = workspace:WaitForChild("Checkpoints")
-- событие сервер → игрок
local checkpointEvent = game.ReplicatedStorage:WaitForChild("CheckpointEvent")
-- игрок зашёл
game.Players.PlayerAdded:Connect(function(player)
-- номер последнего пройденного чекпоинта
local index = Instance.new("IntValue")
-- имя
index.Name = "Index"
-- ещё ничего не прошёл
index.Value = 0
-- храним в игроке
index.Parent = player
-- персонаж появился (в начале и после смерти)
player.CharacterAdded:Connect(function(character)
-- последний пройденный чекпоинт
local last = checkpoints:FindFirstChild(tostring(index.Value))
-- уже что-то прошёл
if last then
-- ждём, пока персонаж загрузится
character:WaitForChild("HumanoidRootPart")
-- ставим у последнего чекпоинта
character:PivotTo(last.Trigger.CFrame + Vector3.new(0, 3, 0))
-- конец проверки
end
-- конец обработчика
end)
-- конец обработчика
end)
-- чей персонаж или чья машина коснулась
local function GetPlayer(otherPart)
-- модель, в которой деталь
local model = otherPart:FindFirstAncestorOfClass("Model")
-- просто деталь
if not model then return nil end
-- это персонаж?
local player = game.Players:GetPlayerFromCharacter(model)
-- да
if player then return player end
-- это машина?
local seat = model:FindFirstChildOfClass("VehicleSeat")
-- за рулём кто-то есть
if seat and seat.Occupant then
-- водитель
return game.Players:GetPlayerFromCharacter(seat.Occupant.Parent)
-- конец проверки
end
-- не игрок
return nil
-- конец функции
end
-- каждый чекпоинт
for _, checkpoint in pairs(checkpoints:GetChildren()) do
-- рамка, сквозь которую проезжают
local trigger = checkpoint:WaitForChild("Trigger")
-- рамки что-то коснулось
trigger.Touched:Connect(function(otherPart)
-- кто это
local player = GetPlayer(otherPart)
-- не игрок — пропускаем
if not player then return end
-- его счётчик
local index = player:FindFirstChild("Index")
-- ещё не создан
if not index then return end
-- это следующий по порядку — пропустить нельзя
if tonumber(checkpoint.Name) == index.Value + 1 then
-- засчитываем
index.Value += 1
-- сообщаем игроку — у него рамка станет зелёной
checkpointEvent:FireClient(player, trigger)
-- конец проверки
end
-- конец обработчика
end)
-- конец перебора
endГде: StarterPlayer → StarterPlayerScripts · LocalScript
Зачем: Красит пройденную рамку в зелёный — только у себя.
-- событие от сервера
local checkpointEvent = game.ReplicatedStorage:WaitForChild("CheckpointEvent")
-- сервер засчитал чекпоинт
checkpointEvent.OnClientEvent:Connect(function(trigger)
-- рамка зелёная — только у этого игрока
trigger.BrickColor = BrickColor.new("Bright green")
-- конец обработчика
end)Запусти Play (или Run) и убедись: