Skip to content

Storage

The Storage namespace contains a set of functions for handling persistent storage of data. To use the Storage API, you must place a Game Settings object in your game and check the Enable Player Storage property on it.

Core storage allows a maximum of 16Kb (16384 bytes) of encoded data to be stored. Any data exceeding this limit is not guaranteed to be stored and can potentially cause loss of stored data. Exceeding the limit will cause a warning to be displayed in the event log when in preview mode.

Storage.SizeOfData() can be used to check the size of data (in bytes) before assigning to storage. If size limit has been exceeded consider replacing strings with numbers or using advanced techniques such as bit packing to reduce the size of data stored.

Class Functions

Class Function Name Return Type Description Tags
Storage.GetPlayerData(Player player) table Returns the player data associated with player. This returns a copy of the data that has already been retrieved for the player, so calling this function does not incur any additional network cost. Changes to the data in the returned table will not be persisted without calling Storage.SetPlayerData(). Server-Only
Storage.SetPlayerData(Player player, table data) <StorageResultCode resultCode, string errorMessage> Updates the data associated with player. Returns a result code and an error message. See below for supported data types. Server-Only
Storage.GetSharedPlayerData(NetReference sharedStorageKey, Player player) table Returns the shared player data associated with player and sharedStorageKey. This returns a copy of the data that has already been retrieved for the player, so calling this function does not incur any additional network cost. Changes to the data in the returned table will not be persisted without calling Storage.SetSharedPlayerData(). Server-Only
Storage.SetSharedPlayerData(NetReference sharedStorageKey, Player player, table data) <StorageResultCode resultCode, string errorMessage> Updates the shared data associated with player and sharedStorageKey. Returns a result code and an error message. See below for supported data types. Server-Only
Storage.SizeOfData(table data) integer Computes and returns the size required for the given data table when stored as Player data. Server-Only
Storage.GetOfflinePlayerData(string playerId) table Requests the player data associated with the specified player who is not in the current instance of the game. This function may yield until data is available, and may raise an error if the player ID is invalid or if an error occurs retrieving the information. If the player is in the current instance of the game, Storage.GetPlayerData() should be used instead. Server-Only
Storage.GetSharedOfflinePlayerData(NetReference sharedStorageKey, string playerId) table Requests the shared player data associated with sharedStorageKey and the specified player who is not in the current instance of the game. This function may yield until data is available, and may raise an error if the player ID is invalid or if an error occurs retrieving the information. If the player is in the current instance of the game, Storage.GetSharedPlayerData() should be used instead. Server-Only

Additional Info

Storage Supported Types
  • boolean
  • Int32
  • Float
  • string
  • Color
  • Rotator
  • Vector2
  • Vector3
  • Vector4
  • Player
  • table

Examples

Example using:

GetOfflinePlayerData

GetSharedOfflinePlayerData

In this example a global leaderboard is enriched with additional data about the player, in this case just their Level, but other data could be included when filling the leaderboard with information. To do this, the script combines a few different concepts about player data. First, the leaderboard data itself provides a list of players for which we then fetch additional data. It's likely the player is not connected to the server, thus offline storage is used, but if they are, regular storage is faster and doesn't yield the thread. Finally, the game may have defined a shared key, resulting in 4 different ways in which the additional player data (level number) is retrieved.

local LEADERBOARD_REF = script:GetCustomProperty("LeaderboardRef")
local STORAGE_KEY = script:GetCustomProperty("StorageKey")

-- Wait for leaderboards to load.
-- If a score has never been submitted it will stay in this loop forever
while not Leaderboards.HasLeaderboards() do
    Task.Wait(1)
end

local leaderboard = Leaderboards.GetLeaderboard(LEADERBOARD_REF, LeaderboardType.GLOBAL)
for i, entry in ipairs(leaderboard) do
    local playerId = entry.id
    local player = Game.FindPlayer(playerId)
    local data
    if player then
        -- The player is on this server, access data directly
        if STORAGE_KEY and STORAGE_KEY.isAssigned then
            -- If there is a shared game key
            data = Storage.GetSharedPlayerData(STORAGE_KEY, player) -- method 1
        else
            data = Storage.GetPlayerData(player) -- method 2
        end
    else
        -- Player is not here, use offline storage. This yields the thread
        if STORAGE_KEY and STORAGE_KEY.isAssigned then
            -- If there is a shared game key
            data = Storage.GetSharedOfflinePlayerData(STORAGE_KEY, playerId) -- method 3
        else
            data = Storage.GetOfflinePlayerData(playerId) -- method 4
        end
    end
    -- Get the additional data
    local playerLevel = data["level"] or 0

    print(i .. ")", entry.name, ":", entry.score, "- Level " .. playerLevel)
end

See also: Storage.GetPlayerData | Game.FindPlayer | Leaderboards.HasLeaderboards | LeaderboardEntry.id | Task.Wait | CoreObject.GetCustomProperty


Example using:

GetPlayerData

This example detects when a player joins the game and fetches their XP and level from storage. Those properties are moved to the player's resources for use by other gameplay systems.

function OnPlayerJoined(player)
    local data = Storage.GetPlayerData(player)
    -- In case it's the first time for this player we use default values 0 and 1
    local xp = data["xp"] or 0
    local level = data["level"] or 1
    -- Each time they join they gain 1 XP. Stop and play the game again to test that this value keeps going up
    xp = xp + 1
    player:SetResource("xp", xp)
    player:SetResource("level", level)
    print("Player " .. player.name .. " joined with Level " .. level .. " and XP " .. xp)
end

Game.playerJoinedEvent:Connect(OnPlayerJoined)

See also: Storage.SetPlayerData | Player.SetResource | Game.playerJoinedEvent | Event.Connect


Example using:

GetSharedPlayerData

This example shows how to read data that has been saved to Shared Storage. Because this is saved via shared-key persistence, the data may have been written by a different game. This allows you to have multiple games share the same set of player data.

For this example to work, there is some setup that needs to be done:

  • Storage needs to be enabled in the Game Settings object.

  • You have to create a shared key.

  • The NetReference for the shared key needs to be added to the script as a custom property.

See the Shared Storage documentation for details on how to create shared keys.

local propSharedKey = script:GetCustomProperty("DocTestSharedKey")
local returnTable = Storage.GetSharedPlayerData(propSharedKey, player)

-- Print out the data we retrieved:
for k, v in pairs(returnTable) do
    print(k, v)
end

Example using:

SetPlayerData

This example detects when a player gains XP or level and saves the new values to storage.

function OnResourceChanged(player, resName, resValue)
    if (resName == "xp" or resName == "level") then
        local data = Storage.GetPlayerData(player)
        data[resName] = resValue
        local resultCode,errorMessage = Storage.SetPlayerData(player, data)
    end
end

function OnPlayerJoined(player)
    player.resourceChangedEvent:Connect(OnResourceChanged)
end

Game.playerJoinedEvent:Connect(OnPlayerJoined)

See also: Storage.GetPlayerData | Player.resourceChangedEvent | Game.playerJoinedEvent | Event.Connect


Example using:

SetSharedPlayerData

This example shows how to write data to the Shared Storage. With this, any maps that you enable with your shared key can all access the same data that is associated with a player. This means that you could have several games where reward, levels, or achievements carry over between them.

For this example to work, there is some setup th at needs to be done:

  • Storage needs to be enabled in the Game Settings object.

  • You have to create a shared key.

  • The NetReference for the shared key needs to be added to the script as a custom property.

See the Shared Storage documentation for details on how to create shared keys.

local propSharedKey = script:GetCustomProperty("DocTestSharedKey")

local sampleData = {
    name = "Philip",
    points = 1000,
    favorite_color = Color.RED,
    skill_levels = {swordplay = 8, flying = 10, electromagnetism = 5, friendship = 30}
}
Storage.SetSharedPlayerData(propSharedKey, player, sampleData)

Tutorials

Check out our Persistent Data Storage in Core tutorial to learn how to apply this API in practice.

Learn More

NetReference on the Core API | Persistent Storage Reference


Last update: September 25, 2021