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!
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).
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)