Simple and easy datastore for beginner scripters!

I wanted to share a very simple datastore for anyone that might need it. The datastore features a script titled “Datastore”, and has a folder parented to it titled “Stats”. Anything you put in the folder titled “Stats” will become the new default values for whatever you want to save!
image
This Datastore will save values ranging from Vector3Values, Color3Values, Booleans, NumberValues, and IntValues which will cover most of what anyone starting out will need. Since this datastore saves Color3Values, you could use it for things like a character creation system, utilizing EyeColor, HairColor, etc. (see below).
image
Whenever a player joins, the “Stats” folder will be cloned and parented to another folder titled “PlayerData”. Each player will have their own stats folder under the “PlayerData” folder which will be named using their UserIds.
I have also included a script called “GivePlayerGold” that will give each player 10 gold every second as a template.
Just use the download below or get it from the Creator Hub link. >>Important: Make sure to parent everything to ServerScriptService!<<
Link to the datastore on Roblox Creator Hub:
[FREE] Basic Datastore - Creator Store (roblox.com)
Datastore download:
BasicDatastore.rbxm (4.3 KB)

Datastore code (Will not compile alone, needs entire file linked above!)
local Datastore = game:GetService("DataStoreService"):GetDataStore("A1") --//This will be the name of your datastore, "A1" for starters.
local StatsFolder = script:WaitForChild("Stats") --//This is a folder containing all the preset stats you desire to save for each player, any values you change will become the new default values.
local UniversalDataFolder = game:GetService("ServerScriptService"):WaitForChild("PlayerData") --//This is the folder where we will store each player's data!

local Serealize = function(Value) --//Vector3Values and Color3Values need to be Serealized (turned into a table essentially) in order to be properly saved to a datastore
	if typeof(Value) == "Vector3" then
		return {Value.x,Value.y,Value.z}
	elseif typeof(Value) == "Color3" then
		return {Value.r, Value.g, Value.b}
	end
end
local DeserealizeVector3 = function(SerializedVector3)--//Vector3Values, once Serealized (basically converted into a table) need to be converted back into Vector3s which is accomplished here
	return Vector3.new(unpack(SerializedVector3))
end

local DeserializeColor3 = function(SerializedColor3)--//Color3Values, once Serealized (basically converted into a table) need to be converted back into Color3s which is accomplished here
	return Color3.new(unpack(SerializedColor3))
end

local SaveData = function(Player)
	local DatastoreKey = Player.UserId --//We are using the Player's ID to generate/grab the Datastore key
	local StatsToSave = {}
	local PlayerStats = UniversalDataFolder:FindFirstChild(tostring(DatastoreKey)) --//Get players stats folder
	if PlayerStats then 
		for i,v in pairs(PlayerStats:GetChildren()) do  --//Get all the stat values within players stat folder and add them to StatsToSave table
			if v:IsA("Vector3Value") or v:IsA("Color3Value") then
				StatsToSave[v.Name] = Serealize(v.Value)
			else
				StatsToSave[v.Name] = v.Value
			end
		end
	end
	Datastore:UpdateAsync(DatastoreKey, function() --//Save player's stats using UpdateAsync()
		return StatsToSave
	end)
	print(Player.Name,"'s' data saved!")
end

local function LoadData(Player)
	local DatastoreKey = Player.UserId--//We are using the Player's ID to generate/grab the Datastore key
	local ExtractedData = Datastore:GetAsync(DatastoreKey)
	local PlayerStats = StatsFolder:Clone() --//Clone the default stats folder 
	PlayerStats.Name = tostring(Player.UserId) --//Name cloned stats folder after Player's UserId
	if ExtractedData then --//Player already has previous data 
		for i,v in pairs(ExtractedData) do
			local ValueToBeSet = PlayerStats:FindFirstChild(i)
			if ValueToBeSet:IsA("Vector3Value") then
				ValueToBeSet.Value = DeserealizeVector3(v)
			elseif ValueToBeSet:IsA("Color3Value") then
				ValueToBeSet.Value = DeserializeColor3(v)
			else
				ValueToBeSet.Value = v
			end
		end
	else--//Player does not already have data, assign new data instead
		local StatsToSave = {}
		for i,v in pairs(PlayerStats:GetChildren()) do 
			if v:IsA("Vector3Value") or v:IsA("Color3Value") then
				StatsToSave[v.Name] = Serealize(v.Value)
			else
				StatsToSave[v.Name] = v.Value
			end
		end
		Datastore:SetAsync(DatastoreKey, StatsToSave)
	end
	PlayerStats.Parent = UniversalDataFolder 
	Player:SetAttribute("DataLoaded",true)
	print(Player.Name,"'s' data loaded!")
end

for i,v in pairs(game:GetService("Players"):GetPlayers()) do --//In case players have already joined during the time it took the script to get here
	LoadData(v)
end

--//Connections
game:GetService("Players").PlayerAdded:Connect(LoadData)
game:GetService("Players").PlayerRemoving:Connect(SaveData)

7 Likes

Im not a beginner scripter, but OMG i am bad at datastores- so this actually really helps lol. Keep up the good work!

1 Like

Can this work with leaderstats? how would I do it

1 Like

Are you looking to have the stats in the datastore display as leaderstats?

Yes like if I had “Coins” that the player earns and can see in their leaderstats, to save in the datastore.

Heya try my edited script of his script with somes of changes/fixes there a give player gold example also

just move the folder inside ServerScriptService and thats it

if you want it to shown in leaderstats just go in my folder then in my script Datastore there will be a Config and when you click on it there an attribute to switch from show in leaderstats or not

image

Enjoy and happy coding!

2 Likes