Skip to content

PlayerTransferData

PlayerTransferData contains information indicating how a player joined or left a game, and their next or previous game ID if they're moving directly from one game to another. Players may opt out of sharing this information by selecting "Hide My Gameplay Activity" or "Appear Offline" in the social panel settings.

Properties

Property Name Return Type Description Tags
reason PlayerTransferReason Indicates how the player joined or left a game. Read-Only
gameId string The ID of the game the player joined from or left to join. Returns nil if the player joined while not already connected to a game or left for a reason other than joining another game. Also returns nil if the player has opted out of sharing this information. Read-Only
sceneId string The scene ID that the player joined from or left to join. May return nil. Read-Only
sceneName string The scene name that the player joined from or left to join. May return nil. Read-Only

Examples

Example using:

gameId

reason

sceneId

sceneName

In this example, transfer data is printed to the event log each time a player joins or leaves the game. While this works in preview mode, there will never be a gameId in that case, and the reason for the transfer will always be BROWSE. Therefore, this example works best when the game is published.

To see the server logs of a published game, select the Game Settings object in the hierarchy and enable "Play Mode Profiling". When playing the published game press F4 to see the profiler and access the logs. You may need a second player joining/leaving to observe the logs while testing the various different reasons.

-- Converts the enum reason into a string, to make the log more readable
function ToStringTransferReason(reason)
    -- Default reason, or player has opted out from sharing this info
    if reason == PlayerTransferReason.UNKNOWN then return "UNKNOWN" end

    -- If they leave to edit their character/collection
    if reason == PlayerTransferReason.CHARACTER then return "CHARACTER" end

    -- If they leave by pressing the "Create" tab
    if reason == PlayerTransferReason.CREATE then return "CREATE" end

    -- If they leave by pressing the "Shop" tab
    if reason == PlayerTransferReason.SHOP then return "SHOP" end

    -- If they join/leave by browsing games or from a URL
    if reason == PlayerTransferReason.BROWSE then return "BROWSE" end

    -- If they join/leave by joining a game their friend is playing
    if reason == PlayerTransferReason.SOCIAL then return "SOCIAL" end

    -- If they join/leave when a game uses player:TransferToGame()
    if reason == PlayerTransferReason.PORTAL then return "PORTAL" end

    -- If they leave from being inactive for longer than the AFK limit
    if reason == PlayerTransferReason.AFK then return "AFK" end

    -- If they close Core or log out
    if reason == PlayerTransferReason.EXIT then return "EXIT" end

    -- Fallback, future-proof
    return "???" .. tostring(reason)
end

-- Given a game ID, retrieves the game's name and author
function FetchGameNameAndAuthor(gameId)
    if gameId then
        -- This yields the thread while the data is retrieved
        local gameInfo = CorePlatform.GetGameInfo(gameId)
        if gameInfo then
            return gameInfo.name .. ", by " .. gameInfo.ownerName
        end
    end
    return ""
end

function OnPlayerJoined(player)
    -- CorePlatform.GetGameInfo creates a delay while the data is being retrieved, during
    -- which time the player object may no longer be valid, so we cache the name first.
    local playerName = player.name
    local transferData = player:GetJoinTransferData()
    local gameId = transferData.gameId
    local reason = ToStringTransferReason(transferData.reason)
    local sceneId = transferData.sceneId
    local sceneName = transferData.sceneName
    local gameBio = FetchGameNameAndAuthor(gameId)
    print(
    "\n Player joined = " .. playerName ..
    "\n from game = " .. tostring(gameId) .. ":" .. gameBio ..
    "\n reason = " .. reason ..
    "\n scene = " .. tostring(sceneName) .. ":" .. tostring(sceneId))
end

function OnPlayerLeft(player)
    -- CorePlatform.GetGameInfo creates a delay while the data is being retrieved, during
    -- which time the player object may no longer be valid, so we cache the name first.
    local playerName = player.name
    local transferData = player:GetLeaveTransferData()
    local gameId = transferData.gameId
    local reason = ToStringTransferReason(transferData.reason)
    local sceneId = transferData.sceneId
    local sceneName = transferData.sceneName
    local gameBio = FetchGameNameAndAuthor(gameId)
    print(
    "\n Player left = " .. playerName ..
    "\n to game = " .. tostring(gameId) .. ":" .. gameBio ..
    "\n reason = " .. reason ..
    "\n scene = " .. tostring(sceneName) .. ":" .. tostring(sceneId))
end

Game.playerJoinedEvent:Connect(OnPlayerJoined)
Game.playerLeftEvent:Connect(OnPlayerLeft)

See also: PlayerTransferReason | Player.TransferToGame | Game.TransferAllPlayersToGame | CoreGameInfo.name



Last update: December 7, 2021