Skip to content

Leaderstats and paths ​

How to wire leaderstats to persisted fields and how dot-path APIs fit together.

Leaderstats integration ​

PlayerState reads a leaderstats table from DefaultData. Keys are display names; values are paths (top-level keys or dotted paths).

lua
local DefaultData = {
    Coins = 0,
    Level = 1,
    Plot = { Likes = 0 },

    leaderstats = {
        ["Coins"] = "Coins",
        ["Level"] = "Level",
        ["Likes"] = "Plot.Likes",
    },
}

Leaderstats instances are created when profile data loads and stay in sync when the backing values changeβ€”never mutate leaderstats directly; update the underlying data (Set, SetPath, batch ops).

Leaderstats order ​

Leaderstats appear in a consistent order. Set LeaderstatsOrder in PlayerStateConfig.Server to a list of display names; stats not in the list follow in alphabetical order (with no list, the whole order is alphabetical). A stat keeps its position when its value switches between whole and decimal numbers.

lua
-- PlayerStateConfig.lua
Server = {
    LeaderstatsOrder = { "Coins", "Level" }, -- "Likes" follows alphabetically
}

Full API behaviour: Leaderboard & leaderstats (server replica + automatic leaderstats), Configuration for defaults and tuning, and Setup for DefaultData placement.

Client-side leaderboard UI ​

Configured global leaderboards (top-N across the game) are separate from HUD leaderstats. See Leaderboard APIs on the server and Client leaderboard for read helpers.

Path notation ​

PlayerState uses ValuePath strings with dots for nested reads and writes (SetPath / GetPath, batches, dictionaries, arrays). Paths are parsed with caching on the server; see Performance for cache notes.

Path examples
lua
PlayerState.SetPath(player, "Settings.MusicEnabled", false)
PlayerState.SetPath(player, "Plot.Buildings.House.Level", 3)

PlayerState.BatchSetValues(player, {
    { path = "Stats.Combat.Weapons.Sword.Damage", value = 25 },
    { path = "Inventory.Tools.Pickaxe.Durability", value = 100 },
})

PlayerState.AddToArray(player, "Achievements", "first_win")
PlayerState.SetInDict(player, "Plot.Buildings", "Windmill", buildingData)

-- Array indices work in paths
local firstItem = PlayerState.GetPath(player, "Items.1")
PlayerState.OnChanged(player, "Items.3", function(newValue) end)

SetPath always creates missing parent tables, on both the server and the client.

OnChanged listeners on a nested path also fire when a parent path is replaced or written with SetValues, so SetValues(player, { Coins = 5 }) reaches an OnChanged(player, "Coins") listener.

Fields under ServerOnlyRoots persist but are not on the player Replica β€” see Server-only data.

Where to read more ​

PlayerState - High-Performance Roblox Data Management