ロブロックス(Roblox)のDataStoreの使い方|抜けても進み具合が残るセーブ機能を画像で解説

制作手順難易度: 中級所要時間: 約40分(目安)情報確認日: 2026年10月5日

「ゲームから抜けても、続きから遊べるようにしたい」「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」に変えます(赤い枠)。

エクスプローラでPartの名前を「Stage2Pad」に書き換えているところに赤い枠Stage2Padのプロパティは次のとおりにします。

プロパティ値
Size8, 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 = 3030秒ごとに保存する
player:GetAttribute("Loaded")読み込みに成功した人だけ保存する(失敗した人の前のデータを1で消さないため)
SetAsyncProgressStoreと同じ名前(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の使い方

次に知りたいことを選ぶ

次に読む記事