「ゲームから抜けても、続きから遊べるようにしたい」「DataStoreって何?どうやって使うの?」
ロブロックス(Roblox)スタジオのDataStore(データストア)の使い方を、実際の画像付きで誰でも簡単に分かるように解説します。この記事では、進んだステージの番号を保存して、次に入ったときに読み込むところまで作ります。保存するのは「Stage」という数字だけで、入り直したアバターはスタート地点に出ます。数字に合わせてステージ2の場所から始めるには、チェックポイントの復活場所とつなぐ処理がもう1つ必要です。
中級ステップ2/28 前の記事:ロブロックス(Roblox)スタジオのローカルスクリプトとは 全体の順番を見る
使うもの:Roblox Studioが起動するパソコン、マウス、キーボード、練習用の作品。パーツやスクリプトの入れ方はオビーの作り方で画像付きで解説しています。
今回の完成状態:下の画像のように、一度ステージ2まで進んでからテストを止め、もう一度始めたときに、右上の「Stage」が「2」のままなら成功です。

DataStoreでできること
DataStoreは、ロブロックスのサーバーに、プレイヤーごとのデータを保存しておく仕組みです。コインの数や進んだステージのように、ゲームから抜けたあとも残しておきたい数字を保存できます。
| 保存の種類 | 抜けたあと | 例 |
|---|---|---|
| チェックポイント(作り方) | 残らない | 倒れたときに途中から復活する |
| DataStore | 残る | 次の日に入っても、Stageの数字が2のまま |
この記事では、「Stage」という1つの数字だけを保存します。最初に入った人は1、緑の床に乗ったら2です。
1. 作品をRobloxに保存する
Studioのホーム画面の左の「テンプレート」から「Baseplate」(赤い枠)を選ぶと、新しいBaseplateが開きます。画像の赤い枠が「次に押す場所」で、画像を押すと大きく表示できます。

DataStoreは、Robloxに保存した作品でしか使えません。新しいBaseplateを開いたら、まず3D画面上部メニューの「ファイル」を開いて「Robloxに保存」(赤い枠)を押します。ボタンの名前や置き場所は、Roblox側の更新で変わることがあります。

名前の欄(画像の1)に名前を入れて、右下の「保存」(画像の2)を押します。この記事では「Asobishift DataStore」と付けました。

この記事の作品では、保存したあと、3D画面の上の作品のタブに「Asobishiftデータストア」と出ています。このあとのテストの文でも、このタブの名前を使います。
2. Studioで保存を試せるようにする
最初の設定では、Studioのテストで保存を試すことができません。3D画面上部メニューの「ファイル」を開いて「バーチャル空間設定」(赤い枠)を押します。

左の「セキュリティ」(赤い枠)を押します。

「StudioのAPIサービスへのアクセスを有効化」(赤い枠)は、最初はオフの状態です。

スイッチ(画像の1)を押してオンにし、右下の「保存」(画像の2)を押します。

この設定は作品ごとです。練習用の作品だけでオンにして、ほかの作品は変えません。
3. ステージ2になる緑の床を置く
エクスプローラの「Workspace」にマウスを乗せて、右に出る「+」を押します(赤い枠)。

一覧の検索欄に「Part」と入れて、一覧の「Part」を押します(赤い枠)。

エクスプローラにできた「Part」を選んでF2キーを押し、名前を「Stage2Pad」に変えます(赤い枠)。
Stage2Padのプロパティは次のとおりにします。
| プロパティ | 値 |
|---|---|
| Size | 8, 1, 8 |
| Position(▼CFrameのすぐ下) | 0, 0.5, -16 |
| 色 | 緑(下の画像の色ボタンと同じ色) |
| Anchored(固定) | オン |
エクスプローラでStage2Padを選んだ状態で、プロパティの検索欄に「Size」と入力し、Sizeの欄を「8, 1, 8」にしてEnterキーを押します(赤い枠)。

続けてStage2Padを選んだまま、プロパティの検索欄を「Position」に書き換えます。Positionは検索するといくつか出てくるので、「▼CFrame」のすぐ下にあるPositionを「0, 0.5, -16」にしてEnterキーを押します(赤い枠)。

Stage2Padを選んだまま、3D画面上部メニューの「ホーム」タブにある「色」ボタン(「素材」ボタンの右)のすぐ右にある小さな矢印を押して色の一覧を開き、緑の「Lime green(ライムグリーン)」を選びます。マスにマウスを乗せると色の名前が出ます。そのあと「色」ボタンのアイコン本体を押すと、床が緑になります。
最後に、Stage2Padを選んだまま、同じ「ホーム」タブの「固定」ボタン(いかりのアイコン。「ロック」ボタンの右)を押します。スポーン地点の前に、緑の床ができました。

エクスプローラのStage2Padにマウスを乗せて「+」を押します。

一覧から「Script」を押します。

エクスプローラでStage2Padの中に入った「Script」を選んだ状態でF2キーを押し、名前を「StageTouch」に変えます。
StageTouchの画面で、中身を全部消して、次のコードを貼り付けます。乗った人のStageが1なら、2に変えるスクリプトです。
-- このScriptは Stage2Pad の中に置く。触れた人のStageを2にする
local pad = script.Parent
local Players = game:GetService("Players")
pad.Touched:Connect(function(hit)
local player = Players:GetPlayerFromCharacter(hit.Parent)
if not player then return end
local stage = player.leaderstats.Stage
if stage.Value < 2 then
stage.Value = 2
end
end)

4. 保存と読み込みのスクリプトを入れる
エクスプローラの「ServerScriptService」にマウスを乗せて、右に出る「+」(赤い枠)を押し、一覧から「Script」を押します。

エクスプローラでServerScriptServiceの中に入った「Script」を選んだ状態でF2キーを押し、名前を「ProgressStore」に変えます。
ProgressStoreの画面で、中身を全部消して、次のコードを貼り付けます。
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local store = DataStoreService:GetDataStore("PlayerProgress")
local loaded = {} -- 読み込みに成功した人だけ true
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local stage = Instance.new("IntValue")
stage.Name = "Stage"
stage.Value = 1 -- 初めて参加した人は1から
stage.Parent = leaderstats
local ok, saved = pcall(function()
return store:GetAsync("player_" .. player.UserId)
end)
if not ok then
-- 読み込みに失敗:今回は保存しない(前のデータを1で上書きしないため)
warn("Stageの読み込みに失敗しました", saved)
return
end
if saved then
stage.Value = saved
end
loaded[player] = true
print(player.Name, "のStageを読み込みました", stage.Value)
end)
Players.PlayerRemoving:Connect(function(player)
if not loaded[player] then return end
loaded[player] = nil
local value = player.leaderstats.Stage.Value
local ok, err = pcall(function()
store:SetAsync("player_" .. player.UserId, value)
end)
if ok then
print(player.Name, "のStageを保存しました", value)
else
warn("Stageの保存に失敗しました", err)
end
end)
続けてエクスプローラでProgressStoreを選んだ状態で、プロパティの検索欄に「RunContext」と入力し、「▼動作」の欄にあるRunContextの一覧から「Server」を選びます。RunContextは、スクリプトをサーバーとプレイヤーのどちらで動かすかを決める設定です。DataStoreは、サーバーで動くScriptからしか使えません。

このスクリプトがしていることは3つです。
| 部分 | していること |
|---|---|
| leaderstats | コードで作るleaderstatsというフォルダーの中の数字(Stage)が、テスト中の画面の右上の一覧に出る |
| GetAsync(読み込み) | 入ってきた人の番号で、前に保存したStageを読み込む。何も保存されていなければ1のまま |
| pcall | 読み込みや保存に失敗しても、スクリプト全体が止まらないようにする |
| SetAsync(保存) | 抜けるときに、今のStageを保存する |
大事なのは、読み込みに失敗したときは、その人のデータを保存しないことです。失敗したまま1を保存すると、前に進めたステージ2が1で上書きされて消えてしまいます。コードの「loaded」は、読み込みに成功した人だけを覚えておくための入れ物です。
5. テストして、続きが残るか確かめる
3D画面の上の作品のタブ「Asobishiftデータストア」を押して3D画面に戻り、F5キーでテストを始めます(タブの名前はパソコンによって違います)。初めてなので、右上のStageは「1」で、出力に「(アカウント名)のStageを読み込みました 1」と出ます(赤い枠)。右上の一覧が出ていないときは、キーボードのTabキーを押すと表示されます。

Wキーで前に歩いて、緑の床に乗ります。右上のStageが「2」に変わります(赤い枠)。

Shift + F5キーでテストを停止します。テストを止めるとゲームから抜けたのと同じ扱いになり、出力に「(アカウント名)のStageを保存しました 2」と出ます(赤い枠)。

3D画面の上の作品のタブ「Asobishiftデータストア」を押して3D画面に戻り、F5キーでテストを始めます(タブの名前はパソコンによって違います)。今度は出力に「(アカウント名)のStageを読み込みました 2」と出て、右上のStageが最初から「2」になっていれば成功です。

公開する前に確かめること
| 確かめること | 大丈夫なサイン |
|---|---|
| 初めて入った人 | Stageが1から始まる |
| 進めてから抜けて入り直す | Stageの数字が進めたときの値になっている |
| 出力に赤い文字や「失敗しました」がない | 読み込み・保存ともにうまくいっている |
この記事のコードは、仕組みを覚えるための一番小さい形です。保存するのは抜けるときの1回だけで、サーバーが閉じるときの保存や、失敗したときのやり直しは入っていません。一定の時間ごとの自動保存は、下の節で足し方を紹介します。公開するゲームで使うときは、下の「AIに頼むときの伝え方」でこれらも足してもらいましょう。
一定の時間ごとに自動で保存する
抜けるときの1回だけの保存では、ゲームが急に止まったときに、それまでの進み具合が残らないことがあります。そこで、決まった時間ごとに自動で保存するスクリプトを足します。この記事では30秒ごとに保存します。
Shift + F5キーでテストを停止します。
まず、ProgressStoreに1行足します。足すのは、loaded[player] = true の行のすぐ下に入る player:SetAttribute("Loaded", true) の1行です。読み込みに成功した人に「Loaded」という印を付けて、自動保存のスクリプトにも分かるようにするためです。
エクスプローラのServerScriptServiceの中の「ProgressStore」をダブルクリックして開き、中身を全部消して、次のコードを貼り付けます。
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local store = DataStoreService:GetDataStore("PlayerProgress")
local loaded = {} -- 読み込みに成功した人だけ true
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local stage = Instance.new("IntValue")
stage.Name = "Stage"
stage.Value = 1 -- 初めて参加した人は1から
stage.Parent = leaderstats
local ok, saved = pcall(function()
return store:GetAsync("player_" .. player.UserId)
end)
if not ok then
-- 読み込みに失敗:今回は保存しない(前のデータを1で上書きしないため)
warn("Stageの読み込みに失敗しました", saved)
return
end
if saved then
stage.Value = saved
end
loaded[player] = true
player:SetAttribute("Loaded", true) -- 自動保存のスクリプトに「読み込めた」と知らせる
print(player.Name, "のStageを読み込みました", stage.Value)
end)
Players.PlayerRemoving:Connect(function(player)
if not loaded[player] then return end
loaded[player] = nil
local value = player.leaderstats.Stage.Value
local ok, err = pcall(function()
store:SetAsync("player_" .. player.UserId, value)
end)
if ok then
print(player.Name, "のStageを保存しました", value)
else
warn("Stageの保存に失敗しました", err)
end
end)
次に、エクスプローラの「ServerScriptService」にマウスを乗せて、右に出る「+」を押し、一覧から「Script」を押します。
エクスプローラでServerScriptServiceの中に入った「Script」を選んだ状態でF2キーを押し、名前を「AutoSave」に変えます。
AutoSaveを選んだまま、プロパティの検索欄に「RunContext」と入力し、RunContextの一覧から「Server」を選びます。
AutoSaveの画面で、中身を全部消して、次のコードを貼り付けます。
-- この Script は ServerScriptService に置く。ProgressStore とは別に、決まった時間ごとに保存する
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local store = DataStoreService:GetDataStore("PlayerProgress")
local AUTOSAVE_INTERVAL = 30 -- 何秒ごとに保存するか
while true do
task.wait(AUTOSAVE_INTERVAL)
for _, player in Players:GetPlayers() do
local leaderstats = player:FindFirstChild("leaderstats")
local stage = leaderstats and leaderstats:FindFirstChild("Stage")
-- 読み込みに成功した人だけ保存する(ProgressStore が付けた印を見る)
if stage and player:GetAttribute("Loaded") then
local ok, err = pcall(function()
store:SetAsync("player_" .. player.UserId, stage.Value)
end)
if ok then
print(player.Name, "のStageを自動で保存しました", stage.Value)
else
warn("自動保存に失敗しました", err)
end
end
end
end
| コードの部分 | していること |
|---|---|
| AUTOSAVE_INTERVAL = 30 | 30秒ごとに保存する |
| player:GetAttribute("Loaded") | 読み込みに成功した人だけ保存する(失敗した人の前のデータを1で消さないため) |
| SetAsync | ProgressStoreと同じ名前(player_ と UserId)で保存するので、次に入ったときに読み込まれる |
3D画面の上の作品のタブ「Asobishiftデータストア」を押して3D画面に戻り、F5キーでテストを始めます(タブの名前はパソコンによって違います)。
以下は、アソビシフト編集部が確かめた結果です。AUTOSAVE_INTERVALで決めた30秒ほど待つと、出力に「(アカウント名)のStageを自動で保存しました」と出て、そのあとも30秒ごとに同じ行が出ます。行の最後の数字は、そのときのStage(右上の一覧の数字)です。手順5の続きでStageが2になっている場合は「…自動で保存しました 2」と出ます。下の画像はStageが1の状態で確かめたときのもので、最後の数字は1です。

保存できる回数には上限があるので、AUTOSAVE_INTERVALを30より小さくしすぎないようにします。
よくある間違い
| 間違い | なぜ困るか | 直し方 |
|---|---|---|
| LocalScriptで保存しようとする | DataStoreはサーバーでしか使えない | ServerScriptServiceのScriptで保存する |
| 数字が変わるたびに保存する | 保存できる回数には上限があり、多すぎると失敗する | 抜けるときや、ステージが変わったときだけ保存する |
| 読み込みに失敗したのに1を保存する | 前のデータが消える | 読み込みに成功した人だけ保存する |
| Studioの設定をオンにしていない | Studioのテストで保存が試せない | 手順2の設定をオンにする |
AIに頼むときの伝え方
保存する数字を増やしたいときは、今のコードを見せて、守ってほしいことを一緒に伝えます。
Roblox StudioのDataStoreで、プレイヤーごとのStageを保存しています。今のコードを貼ります。
Stageに加えて、コインの数も保存したいです。
サーバーが閉じるとき(BindToClose)にも保存し、保存に失敗したときは数回やり直すようにしてください。
読み込みに失敗したときは前のデータを上書きしない、という今の決まりは変えないでください。
ScriptはServerScriptServiceに置きます。直したコードと、2人で確かめる方法を教えてください。
よくある質問
保存したデータを消して、最初から試したいときは?
練習中なら、保存に使う名前(コードの「PlayerProgress」)を別の名前に変えると、何も保存されていない状態から試せます。自動保存のAutoSaveも入れているときは「PlayerProgress」が2つのスクリプトにあるので、両方を同じ新しい名前に変えます。エクスプローラのServerScriptServiceの中の「ProgressStore」をダブルクリックして開き、コードの3行目の「PlayerProgress」を書き換えます。続けて「AutoSave」をダブルクリックして開き、コードの4行目の「PlayerProgress」を同じ名前に書き換えます。片方だけ変えると、読み込みと自動保存が別の場所を使ってしまいます。
公開したあとも、この設定は必要?
「StudioのAPIサービスへのアクセスを有効化」は、Studioのテストで保存を試すための設定です。公開したゲームを遊ぶ人のデータは、この設定がなくても保存されます。
ただし、この設定をオンにしたStudioのテストは、公開中のゲームと同じ保存データを読み書きします。Robloxの公式の説明でも、遊んでいる人のデータを上書きしないように、公開中のゲームではオンにせず、テスト用に分けた作品でオンにするよう書かれています。人に遊んでもらう作品を作るときは、この記事の練習用の作品とは別の作品にしましょう。
次は、ボタンからサーバーに合図を送る仕組みを作ります。次のステップ(中級 3/28)
次に知りたいことを選ぶ
- 次のステップ:ボタンからサーバーに合図を送る仕組みを作ります → ロブロックス(Roblox)のRemoteEventの使い方
- スクリプトが思いどおりに動かない → ロブロックス(Roblox)でスクリプトが動かないときの確認手順
- 作ったゲームを友達に遊んでもらいたい → ロブロックス(Roblox)のゲームを公開する方法