Skip to content

Events ​

Data Manipulation Guidelines

BeforeSave & ProfileLoaded: Use PlayerState functions for data changes (recommended) as they provide validation, leaderstats sync, and proper error handling. Direct data manipulation via the data parameter bypasses these safeguards.

ProfileUnloaded: PlayerState functions are disabled. Only use direct data access via the data parameter for read-only operations or external system synchronization.

BeforeSave() ​

BeforeSave:Connect(listener)

Fired before player data is saved, allowing for final data modifications.

Parameters: listener: (player: Player, data: PlayerData) -> ()
Returns: Connection - Event connection for disconnecting

Example
lua
PlayerState.BeforeSave:Connect(function(player, data)
    -- Use PlayerState functions for data changes (recommended)
    PlayerState.Set(player, "LastSaveTime", os.time())
    PlayerState.SetPath(player, "Stats.TotalPlayTime", data.Stats.PlayTime or 0)

    -- Direct data manipulation bypasses validation (use sparingly)
    data.FinalCoins = data.Coins -- Direct access for read-only operations

    print(`Saving data for {player.Name}`)
end)

Note

Fired before automatic saves with PlayerState functions working normally. Use PlayerState functions for data changes (recommended) as they provide validation and leaderstats sync.


ProfileLoaded() ​

ProfileLoaded:Connect(listener)

Fired when a player's profile data has been loaded and is ready for use.

Parameters: listener: (player: Player, data: PlayerData) -> ()
Returns: Connection - Event connection for disconnecting

Example
lua
PlayerState.ProfileLoaded:Connect(function(player, data)
    -- Use PlayerState functions for data changes (recommended)
    PlayerState.Set(player, "JoinTime", os.time())
    PlayerState.SetPath(player, "Stats.Logins", (data.Stats.Logins or 0) + 1)

    -- Read data for initialization logic
    print(`{player.Name}'s data loaded with {data.Coins} coins`)

    -- Setup player-specific features
    setupPlayerUI(player)
end)

Note

Fired after PlayerState.Init() completes successfully. PlayerState functions work normally - use them for data changes (recommended) for validation and proper sync.


ProfileUnloaded() ​

ProfileUnloaded:Connect(listener)

Fired when a player's profile session ends and data is being unloaded.

Parameters: listener: (player: Player, data: PlayerData) -> ()
Returns: Connection - Event connection for disconnecting

Example
lua
PlayerState.ProfileUnloaded:Connect(function(player, data)
    -- Cleanup player-specific systems
    print(`{player.Name}'s profile unloaded`)

    -- Direct data access only - PlayerState functions don't work here
    local finalCoins = data.Coins
    local playTime = data.Stats.PlayTime or 0

    -- Save to external systems if needed
    saveToAnalytics(player.UserId, finalCoins, playTime)
end)

Note

Fired when profile session ends. PlayerState functions do NOT work during this event - only direct data access via the data parameter is available for read-only operations.


MigrationResult ​

MigrationResult:Connect(listener)

Fired when legacy migration completes for a player. Use for logging, analytics, or debugging migration behavior.

Parameters: listener: (player: Player, result: MigrationResult, data: PlayerData) -> ()
Returns: Connection - Event connection for disconnecting

Result fields: applied, legacyFound, markerWritten, keyUsed, strategy, markerPath, continuous, reason

Example
lua
PlayerState.MigrationResult:Connect(function(player, result, data)
    print("Migration for", player.Name, result.applied, result.reason, result.strategy, result.keyUsed)
end)

See Legacy Data Migration for full documentation.

PlayerState - High-Performance Roblox Data Management