Data Persistence Complete Guide: Difference between revisions

From Legacy Roblox Wiki
Jump to navigationJump to search
>Flurite
No edit summary
m Added category
 
(11 intermediate revisions by 4 users not shown)
Line 1: Line 1:
__TOC__
{{NonStandard|reason=Data persistence was added in 2011 and requires the launcher or revival to support it.}}
 
== Introduction ==
== Introduction ==
''Data Persistence'' saves player's progress in a game. This is a complete tutorial on how it works. There are 8 different methods on how to use it.
''Data Persistence'' saves player's progress in a game. This is a complete tutorial on how it works. There are 8 different methods on how to use it.
Line 9: Line 8:
This first part is a tutorial on how to save a number. In an example we will be saving the players Level, which is a IntValue in the leaderboard. The first part we need is an event to fire when the player is leaving the game. The event we will be using is the 'PlayerRemoving' event.
This first part is a tutorial on how to save a number. In an example we will be saving the players Level, which is a IntValue in the leaderboard. The first part we need is an event to fire when the player is leaving the game. The event we will be using is the 'PlayerRemoving' event.
<pre>
<pre>
game.Players.PlayerRemoving:connect(function(p)
game.Players.PlayerRemoving:connect(function(player)


end)
end)
</pre>
</pre>
The 'PlayerRemoving' event returns one argument, the player that is being removed. Now just in-case they just entered and lost connection, we don't want it to error and we need to wait for them to connect to ROBLOX data-sharing. For this, we will use the 'WaitForDataReady()' event.
The 'PlayerRemoving' event handler receives one argument, the player that is being removed. Now, we don't want it to error if a player just entered and lost connection, so need to wait for them to connect to ROBLOX data-sharing. For this, we will use the 'WaitForDataReady()' method.
<pre>
<pre>
game.Players.PlayerRemoving:connect(function(p)
game.Players.PlayerRemoving:connect(function(player)
     p:WaitForDataReady()
     player:WaitForDataReady()
end)
end)
</pre>
</pre>
You now have an event that fires when a player leaves, and waits for their data to load. Now the next thing we want to do is find their leaderstats. A good way to do it is finding a child of the player that matches the name of 'leaderstats' using the :FindFirstChild() method.
You now have an event that fires when a player leaves, and waits for their data to load. Now the next thing we want to do is find their leaderstats. A good way to do it is finding a child of the player that matches the name of 'leaderstats' using the :FindFirstChild() method.
<pre>
<pre>
game.Players.PlayerRemoving:connect(function(p)
game.Players.PlayerRemoving:connect(function(player)
     p:WaitForDataReady()
     player:WaitForDataReady()
     ls = p:FindFirstChild("leaderstats")
 
     local stats = player:FindFirstChild("leaderstats")
    if not stats then return end
end)
end)
</pre>
</pre>
Now that "ls" is searching for leaderstats.
Now that "stats" is searching for leaderstats.
<pre>
<pre>
game.Players.PlayerRemoving:connect(function(p)
game.Players.PlayerRemoving:connect(function(player)
     p:WaitForDataReady()
     player:WaitForDataReady()
    ls = p:FindFirstChild("leaderstats")
    if ls then


     end
     local stats = player:FindFirstChild("leaderstats")
    if not stats then return end
end)
end)
</pre>
</pre>
The "if ls then" Checks to see if the leaderstats is there. Now we can move on to finding the Level value in the leaderstats.
The "if not stats then return end" checks to see if the leaderstats is there, and if not, exits the function. Now we can move on to finding the Level value in the leaderstats.
<pre>
<pre>
game.Players.PlayerRemoving:connect(function(p)
game.Players.PlayerRemoving:connect(function(player)
     p:WaitForDataReady()
     player:WaitForDataReady()
     ls = p:FindFirstChild("leaderstats")
 
     if ls then
     local stats = player:FindFirstChild("leaderstats")
        lev = ls:FindFirstChild("Level")
     if not stats then return end
    end
 
    local level = stats:FindFirstChild("Level")
end)
end)
</pre>
</pre>
Now 'lev' is finding a child of 'ls' named 'Level', as with the leaderstats, we need to make sure this exists by using an 'if' statement.
As with finding the leaderstats in the player, we need to make sure there is a level in the leaderstats by using an 'if' statement.
<pre>
<pre>
game.Players.PlayerRemoving:connect(function(p)
game.Players.PlayerRemoving:connect(function(player)
     p:WaitForDataReady()
     player:WaitForDataReady()
     ls = p:FindFirstChild("leaderstats")
 
     if ls nil then
     local stats = player:FindFirstChild("leaderstats")
        lev = ls:FindFirstChild("Level")
     if not stats then return end
        if lev then


        end
    local level = stats:FindFirstChild("Level")
     end
     if not level then return end
end)
end)
</pre>
</pre>
Now if it does exist, we save its value. To do this you use the SaveNumber method.
Now if it does exist, we save its value. To do this you use the SaveNumber method.
<pre>
<pre>
game.Players.PlayerRemoving:connect(function(p)
game.Players.PlayerRemoving:connect(function(player)
     p:WaitForDataReady()
     player:WaitForDataReady()
     ls = p:FindFirstChild("leaderstats")
 
     if ls nil then
     local stats = player:FindFirstChild("leaderstats")
        lev = ls:FindFirstChild("Level")
     if not stats then return end
        if lev then
 
            p:SaveNumber("Level", lev.Value)
    local level = stats:FindFirstChild("Level")
        end
    if not level then return end
    end
 
    player:SaveNumber("Level", level.Value)
end)
end)
</pre>
</pre>
Line 76: Line 77:
=== Save String ===
=== Save String ===


Using SaveString is alot like SaveNumber. This can be useful for saving player's chat's. I don't know what the point of that would be, maybe to get a few in-game mods to look through everyone's chat's every so often. Well let's get on to the tutorial then. The first thing we need to do is make an event fire when the player leaves the game.
Using SaveString is a lot like SaveNumber. This can be useful for saving player's chat's. I don't know what the point of that would be, maybe to get a few in-game mods to look through everyone's chat's every so often. Well let's get on to the tutorial then. The first thing we need to do is make an event fire when the player leaves the game.
<pre>
<pre>
game.Players.PlayerRemoving:connect(function(p)
game.Players.PlayerRemoving:connect(function(p)
Line 96: Line 97:
     p:WaitForDataReady()
     p:WaitForDataReady()
     c = p:FindFirstChild("Chats")
     c = p:FindFirstChild("Chats")
     if c nil then
     if c then
</pre>
</pre>
Now that line is checking to make sure it exists. Using the SaveString method we can save it's value.
Now that line is checking to make sure it exists. Using the SaveString method we can save it's value.
Line 103: Line 104:
     p:WaitForDataReady()
     p:WaitForDataReady()
     c = p:FindFirstChild("Chats")
     c = p:FindFirstChild("Chats")
     if c nil then
     if c then
         p:SaveString("Chats", c.Value)
         p:SaveString("Chats", c.Value)
</pre>
</pre>
Line 111: Line 112:
     p:WaitForDataReady()
     p:WaitForDataReady()
     c = p:FindFirstChild("Chats")
     c = p:FindFirstChild("Chats")
     if c nil then
     if c then
         p:SaveString("Chats", c.Value)
         p:SaveString("Chats", c.Value)
     end
     end
Line 342: Line 343:
     p:WaitForDataReady()
     p:WaitForDataReady()
</pre>
</pre>
Now that we have the players data loaded. We can load a saved boolean. Lets use the variable played for this. The variable will become true if they have played, false if they have not.
Now that we have the players data loaded. We can load a saved boolean. Let's use the variable played for this. The variable will become true if they have played, false if they have not.
<pre>
<pre>
game.Players.PlayerAdded:connect(function(p)
game.Players.PlayerAdded:connect(function(p)
Line 418: Line 419:
*[[DataComplexity (Property)|Data Complexity]]
*[[DataComplexity (Property)|Data Complexity]]
*[[Data Persistence Tutorial|What is Data Persistence?]]
*[[Data Persistence Tutorial|What is Data Persistence?]]
[[Category:Scripting Tutorials]]

Latest revision as of 03:01, 17 May 2024

Ouch!
The following article, Data Persistence Complete Guide, mentions a feature exclusive to certain versions of the client.
Specifically: Data persistence was added in 2011 and requires the launcher or revival to support it.


Introduction

Data Persistence saves player's progress in a game. This is a complete tutorial on how it works. There are 8 different methods on how to use it.

Saving

Save Number

This first part is a tutorial on how to save a number. In an example we will be saving the players Level, which is a IntValue in the leaderboard. The first part we need is an event to fire when the player is leaving the game. The event we will be using is the 'PlayerRemoving' event.

game.Players.PlayerRemoving:connect(function(player)

end)

The 'PlayerRemoving' event handler receives one argument, the player that is being removed. Now, we don't want it to error if a player just entered and lost connection, so need to wait for them to connect to ROBLOX data-sharing. For this, we will use the 'WaitForDataReady()' method.

game.Players.PlayerRemoving:connect(function(player)
    player:WaitForDataReady()
end)

You now have an event that fires when a player leaves, and waits for their data to load. Now the next thing we want to do is find their leaderstats. A good way to do it is finding a child of the player that matches the name of 'leaderstats' using the :FindFirstChild() method.

game.Players.PlayerRemoving:connect(function(player)
    player:WaitForDataReady()

    local stats = player:FindFirstChild("leaderstats")
    if not stats then return end
end)

Now that "stats" is searching for leaderstats.

game.Players.PlayerRemoving:connect(function(player)
    player:WaitForDataReady()

    local stats = player:FindFirstChild("leaderstats")
    if not stats then return end
end)

The "if not stats then return end" checks to see if the leaderstats is there, and if not, exits the function. Now we can move on to finding the Level value in the leaderstats.

game.Players.PlayerRemoving:connect(function(player)
    player:WaitForDataReady()

    local stats = player:FindFirstChild("leaderstats")
    if not stats then return end

    local level = stats:FindFirstChild("Level")
end)

As with finding the leaderstats in the player, we need to make sure there is a level in the leaderstats by using an 'if' statement.

game.Players.PlayerRemoving:connect(function(player)
    player:WaitForDataReady()

    local stats = player:FindFirstChild("leaderstats")
    if not stats then return end

    local level = stats:FindFirstChild("Level")
    if not level then return end
end)

Now if it does exist, we save its value. To do this you use the SaveNumber method.

game.Players.PlayerRemoving:connect(function(player)
    player:WaitForDataReady()

    local stats = player:FindFirstChild("leaderstats")
    if not stats then return end

    local level = stats:FindFirstChild("Level")
    if not level then return end

    player:SaveNumber("Level", level.Value)
end)

There, you have just saved a players level. Now, you just need to add ends to close the functions and 'if' statements. So here is our finished script. This completes the 'Save number' section.

Save String

Using SaveString is a lot like SaveNumber. This can be useful for saving player's chat's. I don't know what the point of that would be, maybe to get a few in-game mods to look through everyone's chat's every so often. Well let's get on to the tutorial then. The first thing we need to do is make an event fire when the player leaves the game.

game.Players.PlayerRemoving:connect(function(p)

Now we have to wait for the player's data to load. Just in-case it wasn't loaded already, we don't want to break the script.

game.Players.PlayerRemoving:connect(function(p)
    p:WaitForDataReady()

Now that we are sure that the data is ready to save/load. We have to find the item we want to save. For now let's just say there is an item called "Chats" in the player.

game.Players.PlayerRemoving:connect(function(p)
    p:WaitForDataReady()
    c = p:FindFirstChild("Chats")

Now "c" is searching for the StringValue called Chats. We next have to make sure it exists.

game.Players.PlayerRemoving:connect(function(p)
    p:WaitForDataReady()
    c = p:FindFirstChild("Chats")
    if c then

Now that line is checking to make sure it exists. Using the SaveString method we can save it's value.

game.Players.PlayerRemoving:connect(function(p)
    p:WaitForDataReady()
    c = p:FindFirstChild("Chats")
    if c then
        p:SaveString("Chats", c.Value)

Now we are almost done, as always when we are finishing we must add in our ends.

game.Players.PlayerRemoving:connect(function(p)
    p:WaitForDataReady()
    c = p:FindFirstChild("Chats")
    if c then
        p:SaveString("Chats", c.Value)
    end
end)

Save Boolean

Save Boolean can be used to check if a player has visited the game before. You don't need an actual bool object to save. Let's get started with an event that fires when a player leaves the game.

game.Players.PlayerAdded:connect(function(p)

Now we have p defining the player who left. Now we must wait for their data to be ready.

game.Players.PlayerAdded:connect(function(p)
p:WaitForDataReady()

Now it's just commen knowledge. In order for them to leave the game they must have entered. So we can assume they have played. We can save a boolean with the value of true to show that they have played.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    p:SaveBoolean("Played", true)

Now the only thing we need is our end

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    p:SaveBoolean("Played", true)
end)

Save Instance

Save Instance can be really useful for Building games. It is how ROBLOX's Building game works. In this example we will use a model where all the player's items are stored. We will call it (p.Name.."'s Bricks"). The first thing we need is our event for when the player leaves the place.

game.Players.PlayerRemoving:connect(function(p)

There! We have out event. Let's add in our WaitForDataReady method just in-case their data hasn't loaded yet.

game.Players.PlayerRemoving:connect(function(p)
    p:WaitForDataReady()

The player's data is now loaded. We must now find the players model.

game.Players.PlayerRemoving:connect(function(p)
    p:WaitForDataReady()
    Model = game.Workspace:FindFirstChild(p.Name.."'s Bricks")

Now that "Model" is searching for the player's model. We can check to see if it exists.

game.Players.PlayerRemoving:connect(function(p)
    p:WaitForDataReady()
       Model = game.Workspace:FindFirstChild(p.Name.."'s Bricks")
    if Model then

If the model exists, we can save the Model. So let's use the SaveInstance method to do so.

game.Players.PlayerRemoving:connect(function(p)
    p:WaitForDataReady()
    Model = game.Workspace:FindFirstChild(p.Name.."'s Bricks")
    if Model then
        p:SaveInstance("BuildingBricks", Model)

And what's the last thing we need? Our ends!

game.Players.PlayerRemoving:connect(function(p)
    p:WaitForDataReady()
    Model = game.Workspace:FindFirstChild(p.Name.."'s Bricks")
    if Model then
        p:SaveInstance("BuildingBricks", Model)
    end
end)

You now have a script that will save a model to a player when they leave.

Loading

Load Number

In the LoadNumber method, you can load a number that a player previously saved. If there was no number saved then the LoadNumber will be 0. Our first line to do this will be for when the player enters the game.

game.Players.PlayerAdded:connect(function(p)

Now p defines the player that was added to the game. Before we can do anything with a players stats, we need to wait until their data is loaded.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()

Now that the player has their data loaded, we should create their leaderstats.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local ls = Instance.new("IntValue", p)
    ls.Name = "leaderstats"
    local lev = Instance.new("IntValue", ls)
    lev.Name = "Level"

Now we have the leaderstats created. But wait! We don't know what to set the value of "lev" to. So this is where we have to use the LoadNumber method to find out what was saved.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local ls = Instance.new("IntValue", p)
    ls.Name = "leaderstats"
    local lev = Instance.new("IntValue", ls)
    lev.Name = "Level"
    SavedLevel = p:LoadNumber("Level")

Now SavedLevel is the value that was previously saved. But if a player never visited before, the value would be 0. You can't be level 0 now can you? This is where we have to check to make sure its not 0

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local ls = Instance.new("IntValue", p)
    ls.Name = "leaderstats"
    local lev = Instance.new("IntValue", ls)
    lev.Name = "Level"
    SavedLevel = p:LoadNumber("Level")
    if SavedLevel == 0 then
        SavedLevel = 1
    end

Now we are sure they will not be Level 0. Now we just have to set the value of the level.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local ls = Instance.new("IntValue", p)
    ls.Name = "leaderstats"
    local lev = Instance.new("IntValue", ls)
    lev.Name = "Level"
    SavedLevel = p:LoadNumber("Level")
    if SavedLevel == 0 then
        SavedLevel = 1
    end
    lev.Value = SavedLevel

We are almost finished! We just have to add in our ends.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local ls = Instance.new("IntValue", p)
    ls.Name = "leaderstats"
    local lev = Instance.new("IntValue", ls)
    lev.Name = "Level"
    SavedLevel = p:LoadNumber("Level")
    if SavedLevel == 0 then
        SavedLevel = 1
    end
    lev.Value = SavedLevel
end)

And we now have a Save/Load level script.

Load String

In this tutorial we will be using the LoadString method. It will also have a script included to add chat's to a string value whenever somebody says something. We first have to start out with an event that fires when a player enter's the game.

game.Players.PlayerAdded:connect(function(p)

Now "p" is defining the player who joined. As always we need to wait for their data to load before we can do anything with it.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()

Now the data is ready. The next thing we should do is create the StringValue in the player called "Chats"

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local SV = Instance.new("StringValue", p)
    SV.Name = "Chats"

Now we have the StringValue inside of the player. We now have to use the LoadString method to know what to set the value as.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local SV = Instance.new("StringValue", p)
    SV.Name = "Chats"
    C = p:LoadString("Chats")

Now that "C" is the loaded string value, we can set the value of chats.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local SV = Instance.new("StringValue", p)
    SV.Name = "Chats"
    C = p:LoadString("Chats")
    SV.Value = C

You have just loaded the value. Now I will add in the script to update the value whenever the user talks. The first thing we need is the .Chatted event

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local SV = Instance.new("StringValue", p)
    SV.Name = "Chats"
    C = p:LoadString("Chats")
    SV.Value = C
    p.Chatted:connect(function(msg)

"msg" is defining what the thing said was. Now we just need to simply update the value.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local SV = Instance.new("StringValue", p)
    SV.Name = "Chats"
    C = p:LoadString("Chats")
    SV.Value = C
    p.Chatted:connect(function(msg)
        SV.Value = SV.Value.."; "..msg

Now we are almost done. We just need to add in our ends.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    local SV = Instance.new("StringValue", p)
    SV.Name = "Chats"
    C = p:LoadString("Chats")
    SV.Value = C
    p.Chatted:connect(function(msg)
        SV.Value = SV.Value.."; "..msg
    end)
end)

Load Boolean

So say you have a gui, you want it to only show the first time a player enters the game. Let's say this gui is inside the script and it's called "ScreenGui". You will use the LoadBoolean method to see if they have played before. Let's start off with our PlayerAdded event.

game.Players.PlayerAdded:connect(function(p)

Now we need to wait for their data to load. "p" is defining this player who enters the game. To wait, you use the WaitforDataReady method.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()

Now that we have the players data loaded. We can load a saved boolean. Let's use the variable played for this. The variable will become true if they have played, false if they have not.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    played = p:LoadBoolean("Played")

Now we can check to see if "played" is false.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    played = p:LoadBoolean("Played")
    if played == false then

After we check to see if it is false, we will clone the ScreenGui into the player's PlayerGui

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    played = p:LoadBoolean("Played")
    if played == false then
        script.ScreenGui:clone().Parent = p.PlayerGui

There, we are almost finished. We just have to add in our ends. After we add those in we are done.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    played = p:LoadBoolean("Played")
    if played == false then
        script.ScreenGui:clone().Parent = p.PlayerGui
    end
end)

Load Instance

We will now load a player's saved bricks. The model will be called (player.Name.."'s Bricks"). The first thing we need is our event for when they enter.

game.Players.PlayerAdded:connect(function(p)

Before we load their bricks, we need to wait for the Data to be Ready.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()

Their data is ready now! We can load their saved bricks using LoadInstance.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    Parts = p:LoadInstance("BuildingBricks")

"Parts" Is the loaded model, we can set it's parent to workspace now.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    Parts = p:LoadInstance("BuildingBricks")
    Parts.Parent = game.Workspace

Before we finish we just need our ends.

game.Players.PlayerAdded:connect(function(p)
    p:WaitForDataReady()
    Parts = p:LoadInstance("BuildingBricks")
    Parts.Parent = game.Workspace
end)

Other

Limitations

  • Data Persistence only works in ROBLOX game Servers. It does not work in Build or Edit mode.
  • A maximum of 45000 data complexity units can be saved for each player in 1 game. data complexity units can be measured using Instance.DataCost
  • If you try to use DataCost in a normal or local script, it will error.
  • PlayerRemoving does not always give enough time to save

See also