Roblox Studioでオブビーを作ると、途中で落ちたプレイヤーが毎回スタート地点へ戻ってしまう問題が出てきます。
そこで必要になるのがチェックポイントです。
プレイヤーがチェックポイントへ触れた位置を記録し、ミスをした後は最後に通過した場所から再開できるようにします。
この記事では、次の機能を作ります。
- 複数のチェックポイントをコースへ配置する
- プレイヤーが触れたステージ番号を記録する
- キャラクターが復活したときに最後の地点へ移動する
- 同じチェックポイントへ何度触れても重複処理しない
今回はゲームを終了するまで記録が残る基本版です。
ゲームを閉じた後も進行状況を残す方法は、DataStoreの記事で解説します。
完成する仕組み
チェックポイントを次の順番で通過するオブビーを想定します。
スタート
↓
Checkpoint1
↓
Checkpoint2
↓
Checkpoint3
↓
ゴール
例えばCheckpoint2へ触れた後に落下すると、復活後のキャラクターはCheckpoint2の少し上へ移動します。
チェックポイントを配置する
まず、Roblox StudioのExplorerで次の構成を作ります。
Workspace
└─ Checkpoints(Folder)
├─ Checkpoint1(Part)
├─ Checkpoint2(Part)
└─ Checkpoint3(Part)
ServerScriptService
└─ CheckpointServer(Script)
WorkspaceへFolderを追加し、名前をCheckpointsにします。その中へチェックポイント用のPartを入れてください。
各Partでは次のプロパティを設定します。
| プロパティ | 設定 | 理由 |
|---|---|---|
| Name | Checkpoint1 | ステージ番号をコードで取得するため |
| Anchored | true | プレイ開始時に落下させないため |
| CanCollide | true | 足場として乗れるようにするため |
| CanTouch | true | Touchedイベントを使うため |
| Color | 好きな色 | 通常の足場と区別するため |
名前の末尾には必ず数字を付けます。CheckpointAのような名前ではステージ番号を取得できません。
ServerScriptServiceへコードを追加する
ServerScriptServiceへScriptを追加し、名前をCheckpointServerにします。最初から入っているコードを削除して、以下を貼り付けてください。
local Players = game:GetService("Players")
local checkpointsFolder = workspace:WaitForChild("Checkpoints")
local lastCheckpointByPlayer = {}
local function getStageNumber(checkpoint)
return tonumber(checkpoint.Name:match("%d+$"))
end
local function getPlayerFromHit(hit)
local character = hit:FindFirstAncestorOfClass("Model")
if not character then
return nil
end
local humanoid = character:FindFirstChildOfClass("Humanoid")
if not humanoid then
return nil
end
return Players:GetPlayerFromCharacter(character)
end
local function activateCheckpoint(checkpoint, hit)
local player = getPlayerFromHit(hit)
if not player then
return
end
local stageNumber = getStageNumber(checkpoint)
if not stageNumber then
warn(checkpoint.Name .. " の末尾に数字がありません")
return
end
local currentStage = player:GetAttribute("Stage") or 0
if stageNumber <= currentStage then
return
end
player:SetAttribute("Stage", stageNumber)
lastCheckpointByPlayer[player] = checkpoint
print(player.Name .. " がステージ " .. stageNumber .. " に到達")
end
local function connectCheckpoint(checkpoint)
if not checkpoint:IsA("BasePart") then
return
end
checkpoint.Touched:Connect(function(hit)
activateCheckpoint(checkpoint, hit)
end)
end
local function setupPlayer(player)
player:SetAttribute("Stage", 0)
player.CharacterAdded:Connect(function(character)
local checkpoint = lastCheckpointByPlayer[player]
if not checkpoint or not checkpoint.Parent then
return
end
character:WaitForChild("HumanoidRootPart")
task.wait()
character:PivotTo(checkpoint.CFrame * CFrame.new(0, 4, 0))
end)
end
for _, checkpoint in ipairs(checkpointsFolder:GetChildren()) do
connectCheckpoint(checkpoint)
end
checkpointsFolder.ChildAdded:Connect(connectCheckpoint)
Players.PlayerAdded:Connect(setupPlayer)
for _, player in ipairs(Players:GetPlayers()) do
setupPlayer(player)
end
Players.PlayerRemoving:Connect(function(player)
lastCheckpointByPlayer[player] = nil
end)
コードの仕組み
チェックポイント番号を取得する
return tonumber(checkpoint.Name:match("%d+$"))
`%d+`は連続する数字、`$`は名前の末尾を表します。`Checkpoint12`なら`12`を取得します。
Partに触れたプレイヤーを特定する
Touchedイベントのhitには、足、腕、アクセサリなど、実際に触れたパーツが入ります。そのため`hit.Parent`だけを見るのではなく、上位のModelを探してHumanoidがあるか確認しています。
Attributeへステージ番号を入れる
player:SetAttribute("Stage", stageNumber)
Attributeを使うと、ExplorerのPlayerから現在のステージ番号を確認できます。将来UIへステージ数を表示するときにも利用できます。
復活後にキャラクターを移動する
character:PivotTo(checkpoint.CFrame * CFrame.new(0, 4, 0))
チェックポイントと同じ位置へ移動するとPartへ埋まる可能性があるため、Y方向へ4 studs上げています。
動作確認の手順
- Studio上部のPlayを押す
- Checkpoint1へ触れる
- ExplorerでPlayerのAttributeが`Stage = 1`になったか確認する
- キャラクターをリセットするか、コースから落下する
- Checkpoint1の上から再開できるか確認する
- Checkpoint2とCheckpoint3でも同じ手順を試す
Outputへ「プレイヤー名 がステージ 1 に到達」と表示されれば、通過判定は動いています。
チェックポイントが動かない原因
Folder名が違う
コードでは`workspace:WaitForChild(“Checkpoints”)`を探しています。Folder名が`Checkpoint`や`checkpoints`になっていないか確認してください。
Scriptを置く場所が違う
このコードはLocalScriptではなく、`ServerScriptService`内のScriptで動かします。
CanTouchがオフになっている
チェックポイントPartの`CanTouch`がfalseだと、`Touched`イベントが発生しません。
Part名の末尾に数字がない
`Checkpoint1`、`Checkpoint2`のように命名します。数字がない場合はOutputへ警告を表示します。
復活位置がPartへ埋まる
キャラクターの大きさに合わせて、`CFrame.new(0, 4, 0)`の`4`を`5`や`6`へ変更してください。
ゲームを閉じた後も保存するには
この記事の`lastCheckpointByPlayer`は、現在のサーバー内だけで使うデータです。プレイヤーがゲームを終了すると消えます。
進行状況を次回のプレイでも復元するには、`Stage`の数値をDataStoreへ保存します。最初は今回の基本版だけで動作を確認し、その後に保存機能を追加するとエラーを切り分けやすくなります。
まとめ
Robloxのチェックポイントは、次の3つを組み合わせて作れます。
- Partの`Touched`で通過を検知する
- PlayerのAttributeへステージ番号を記録する
- `CharacterAdded`で最後のPartへキャラクターを移動する
これで、オブビーを途中から再開できるようになりました。
次はコース上にコインを置き、プレイヤーごとの獲得数を画面へ表示してみましょう。
関連記事



コメント