Appearance
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.