How To Make A Simple Data Store!

I’ve seen that a lot of people have struggled to create Data Stores, so I have created a Plugin to help you do just that! This is how to use the plugin, and all of its features!

The Plugin

It may look very simple and easy to use, well IT IS!

Features

Each tab has its own respective value changes, everything is customizable!

image

Update the ‘DataVersion’ value to reset everybody’s stats! Tick the ‘Saving’ bool value to toggle saving on and off!

FAQ

Q: Why would you need to toggle saving on and off?
A: If you are trying to test something in studio, and you don’t want your progress to save!

Q: How do you reset the player stats?
A: Change the ‘DataVersion’ value found inside of the script to something that it has not been to before! (e.g change the value from 0 to 1 if 1 has not been used and vice versa)

Q: How do you insert the data store?
A: Click the green plus (+) icon when you open the plugin! Currently the red minus (-) icon doesn’t do anything haha

Q: Ive inserted a value, how do I insert another one?
A: Re Open the plugin, it will take you back to the first page!

Q: Can I insert 2 values of the same name into the same folder?
A: No unfortunately you can not because the data store will not know which instance to apply each value too. What you can do though, is insert the same name item into 2 different named folders!

Q: Can I insert values into the player, and not a folder?
A: Currently no, but I will make a way to do this in a future update!

Links

YouTube Tutorial Video: How To Make A DATASTORE In 5 MINUTES! - YouTube

Plugin itself: DataStorer - Roblox

Thats all for now! Have a wonderful day!

13 Likes

Nice, but…this isn’t really a tutorial since it’s a plugin it should be in community resources.

2 Likes

ohh ok ok haha my bad. I’ll change it

Absolutly amazing, the way this DataStore is so easy to edit and well made just blows my mind, 10/10 work my guy, keep it up! ^^

1 Like

uhhh @fuzzlea i have an issue / bug
i have an number value called story
i’m unsure if its not saving properly or if its not loading properly
story is set to 0 when you first join the game
after talking to an npc, it is set to 1
However, when i join back after talking to the NPC, it loads as 0 again. This isn’t in a localscript or anything, and there are no errors in the output.

1 Like

thanks bro! :smiley: <3 im glad I was able to help

show me the explorer and the script itself

1 Like

image

local myDataStore = DataStoreService:GetDataStore("Data#"..script.DataVersion.Value)

local saving = script["Saving"]

game.Players.PlayerAdded:Connect(function(plr)	
	local key = plr.UserId.."'s' Data"
	local data = myDataStore:GetAsync(key)

	print(data)

	for _, folder in pairs(script:GetChildren()) do

		if folder:IsA("Folder") then

			local fc = folder:Clone()
			fc.Parent = plr

			if saving then
				for _, item in pairs(fc:GetChildren()) do			
					if data then
						item.Value = data[item.Name.." "..folder.Name]
					else
						warn("There is no data!")
					end
				end
			end
		end
	end

	
	local bar = plr.PlayerGui:WaitForChild("ScreenGui").Levels.EXPbar
	local level = plr.PlayerGui:WaitForChild("ScreenGui").Levels.MainPattern.Level
	local levelval = plr:WaitForChild("leaderstats").Level.Value
	local XPval = plr:WaitForChild("nonleaderstats").XP.Value
	level.Text = tostring(levelval)
	bar.Text = tostring(XPval).." EXP / "..tostring((levelval*100)+100).." EXP"
	
	
	local coins = plr.PlayerGui:WaitForChild("ScreenGui").Icons.Coins.TextLabel
	local aurumval = plr:WaitForChild("leaderstats").Aurum.Value
	coins.Text = tostring(aurumval)
	
	
	local frame = plr.PlayerGui:WaitForChild("ScreenGui").Dialogue
	local but = frame.TextButton
	frame.Position = UDim2.new(0.106, 0,1, 0)
	local prox = game.Workspace.TutorialNPC.HumanoidRootPart.ProximityPrompt
	local option = frame.Option
	local sound = Instance.new("Sound")
	sound.SoundId = "rbxassetid://9120299893"
	sound.Parent = game.Workspace
	option.Position = UDim2.new(0.937, 0, 1.8, 0)
	local cam = game.Workspace.CurrentCamera
	local man = game.Workspace.TutorialNPC
	local storytext = plr.PlayerGui:WaitForChild("ScreenGui").Storyline.StorylineText
	local storyval = plr:WaitForChild("story").story.Value
	if storyval == 0  then
		storytext.Text = "0"
	elseif storyval == 1 then
		storytext.Text = "1"
	end
	
	print(storyval)
	
	local function appear()
		cam.CameraType = Enum.CameraType.Fixed
		cam.Focus = man.Head.CFrame
		plr.PlayerGui.ScreenGui.Icons.Visible = false
		plr.PlayerGui.ScreenGui.ShopFrame.Visible = false
		plr.PlayerGui.ScreenGui.Storyline.Visible = false
		plr.PlayerGui.ScreenGui.Levels.Visible = false
		frame.Position = UDim2.new(0.106, 0,1, 0)
		for i = 1, 0.65, -0.05 do
			frame.Position = UDim2.new(0.106, 0,i, 0)
			wait(0.001)
		end

	end
	
	
	local function disappear()
		plr.PlayerGui.ScreenGui.Icons.Visible = true
		plr.PlayerGui.ScreenGui.Storyline.Visible = true
		plr.PlayerGui.ScreenGui.Levels.Visible = true
		frame.Position = UDim2.new(0.106, 0,65, 0)
		for i = 0.65, 1.2, 0.05 do
			frame.Position = UDim2.new(0.106, 0,i, 0)
			wait(0.001)
		end
		cam.CameraType = Enum.CameraType.Custom
		cam.CameraSubject = plr.Character.Humanoid
	end
	
	
	local function typewrite(text)
		local delays = 0.05
		for count = 1, #text, 1 do
			but.Text = string.sub(text, 1, count)
			sound:Play()
			wait(delays)
			but.MouseButton1Down:Connect(function()
				delays = 0.01
			end)
			but.MouseButton1Up:Connect(function()
				delays = 0.05
			end)
		end
	end


	local function optionappear(text)
		option.Position = UDim2.new(0.937, 0, 1.8, 0)
		option.Text = text
		for j = 1.8, 0, -0.1 do
			option.Position = UDim2.new(0.937, 0, j, 0)
			wait(0.001)
		end
		option.MouseButton1Click:Connect(function()
			for K = 0, 1.8, 0.1 do
				option.Position = UDim2.new(0.937, 0, K, 0)
				wait(0.001)
			end
			typewrite("a")
			wait(1)
			typewrite("b")
			wait(1)
			typewrite("c")
			wait(1)
			typewrite("d")
			wait(1)
			typewrite("e")
			wait(1)
			typewrite("f")
			storytext.Text = "f"
			wait(1)
			disappear()

		end)
	end
	prox.Triggered:Connect(function(player)
		if storyval == 0 then
			appear()
			typewrite("g")
			wait(1)
			optionappear("h")
			storyval = 1
		elseif storyval == 1 then
			appear()
			typewrite("f")
			wait(1)
			disappear()
		end
	end)

end)

if saving then
	local function create_table(plr)
		local player_stats = {}

		for _, folder in pairs(script:GetChildren()) do
			if folder:IsA("Folder") then
				for _, stat in pairs(plr:FindFirstChild(folder.Name):GetChildren()) do
					player_stats[stat.Name.." "..folder.Name] = stat.Value
				end
			end
		end

		return player_stats
	end

	game.Players.PlayerRemoving:Connect(function(plr)
		local player_stats = create_table(plr)

		local succes, err = pcall(function()
			local key = plr.UserId.."'s' Data"
			myDataStore:SetAsync(key, player_stats)
		end)

		if succes then
			print("Saved Data Correctly!")
		else
			warn(err)
		end
	end)
end```

No errors in the output. Aurum saves properly, and I’m not sure about XP and level, but story definitely does not. All of them are Number Values. Everything works properly, and the value changes, but once you leave the server, it is back to 0 again.

Good post. Good plugin. I like it.

any potential reasons as to why this might be?

i keep on getting a error “Value is not a valid member of Folder “Players.Stacy.Stats.Inventory” - Server” on line 15

and on line 14 "ServerScriptService.DataStorer_DataStore:14: attempt to index nil with ‘GetChildren’ - "

Hope you don’t mind but I tweaked your code a bit for a version that saves data every time the value is updated, Useful for systems with unlockables, Just gonna leave it here for others :slight_smile:

local DataStoreService = game:GetService("DataStoreService")
local config = script:WaitForChild("datastore_config")
local myDataStore = DataStoreService:GetDataStore("$Data$!"..config:FindFirstChild("DataVersion").Value)

local saving = config:FindFirstChild("Saving")
local autoSave = config:FindFirstChild("AutoSave")

local function create_table(plr)
	local player_stats = {}

	for _, folder in pairs(script:FindFirstChild("Plr"):GetChildren()) do
		if folder:IsA("Folder") then
			print(folder)
			for _, stat in pairs(plr:FindFirstChild(folder.Name):GetChildren()) do
				player_stats[stat.Name.." "..folder.Name] = stat.Value
			end
		end
	end

	return player_stats
end

local function saveData(plr)
	local player_stats = create_table(plr)

	local succes, err = pcall(function()
		local key = plr.UserId.."'s' Data"
		myDataStore:SetAsync(key, player_stats)
	end)

	if succes then
		print("Saved Data Correctly!")
	else
		warn(err)
	end
end

game.Players.PlayerAdded:Connect(function(plr)
	local key = plr.UserId.."'s' Data"
	local data = myDataStore:GetAsync(key)

	print(data)

	for _, folder in pairs(script:FindFirstChild("Plr"):GetChildren()) do
		if folder:IsA("Folder") then
			local fc = folder:Clone()
			fc.Parent = plr

			if saving.Value == true then
				for _, item in pairs(fc:GetChildren()) do
					if data then
						item.Value = data[item.Name.." "..folder.Name]
					else
						warn("There is no data!")
					end

					-- Add a Changed event to each item's Value property
					item.Changed:Connect(function(newValue)
						-- Save the player's data when a value is changed
						saveData(plr)
						print("Saved", newValue)
					end)
				end
			end
		end
	end
end)


game.Players.PlayerRemoving:Connect(function(plr)
	if saving.Value == true then
		saveData(plr)
	end
end)
3 Likes