Player Management

Manage players and sessions in your Board game.

Overview

Board supports multiple players in a single session. Each player has a profile with a name, avatar, and unique identifier. The SDK tracks who is playing and associates save games with the right players.

Player Types

Board has three player types:

Type Description
Profile A persistent identity stored on Board
Guest A temporary player for the current session only
AI A game-controlled player selected through the player selector

Access the type via player.type:

using Board.Core;
using Board.Session;

foreach (var player in BoardSession.players)
{
    if (player.type == BoardPlayerType.Profile)
    {
        // Persistent identity stored on Board
    }
    else if (player.type == BoardPlayerType.Guest)
    {
        // Temporary player for this session only
    }
    else if (player.type == BoardPlayerType.AI)
    {
        // Game-controlled AI player
    }
}

Accessing Session Players

The current players are available through BoardSession.players:

using Board.Session;

// Get all players in the current session
BoardSessionPlayer[] players = BoardSession.players;

foreach (var player in players)
{
    Debug.Log($"Player: {player.name}");
}

At launch, BoardSession.players contains the active profile. The session always requires at least one Profile player. This constraint is enforced by Board and cannot be bypassed.

Player Properties

Each BoardSessionPlayer provides:

Property Type Description
name string Display name (not guaranteed unique)
playerId string App-specific persistent identifier
sessionId int Unique identifier for this session
avatarId string Avatar identifier
avatar Texture2D Avatar texture (loads asynchronously)
type BoardPlayerType Profile, Guest, or AI
aiTypeIndex int Index into registered AI types (-1 if not an AI player)

Player ID vs Session ID

  • playerId - Persistent across sessions for the same profile playing the same app. Use for tracking player-specific data like high scores or preferences. Guest players have randomly generated playerId values that differ each session.
  • sessionId - Unique only within the current session. Use for identifying players during gameplay.
// For persistent player data, use playerId
PlayerPrefs.SetInt($"highscore_{player.playerId}", score);

// For session-specific tracking, use sessionId
playerStates[player.sessionId] = new PlayerState();

Note: When loading a save game, if a profile associated with that save no longer exists, Board replaces it with a Guest player. The Guest inherits the original sessionId but receives a new playerId. This preserves in-game state keyed by sessionId while breaking persistent data associations.

Responding to Player Changes

Subscribe to BoardSession.playersChanged to react when players join or leave:

void Start()
{
    BoardSession.playersChanged += OnPlayersChanged;
}

void OnDestroy()
{
    BoardSession.playersChanged -= OnPlayersChanged;
}

void OnPlayersChanged()
{
    // Refresh player list UI
    RefreshPlayerDisplay();

    // Check if expected players are still present
    ValidateGameState();
}

Active Profile

The system-wide active profile is available separately:

// Get the currently active Board profile
BoardPlayer activeProfile = BoardSession.activeProfile;

// React to profile changes
BoardSession.activeProfileChanged += OnActiveProfileChanged;

The active profile may or may not be in the current session’s players array.

Loading Avatars

Player avatars load asynchronously. Handle the avatarLoaded event:

void DisplayPlayer(BoardSessionPlayer player)
{
    // Set placeholder or current avatar
    playerImage.texture = player.avatar;

    // Update when loaded
    player.avatarLoaded += OnAvatarLoaded;
}

void OnAvatarLoaded(BoardPlayer player)
{
    playerImage.texture = player.avatar;
}

For players not in the session (e.g., in save game UI), use the default avatar:

var defaultAvatar = await BoardPlayer.GetDefaultAvatar();
unknownPlayerImage.texture = defaultAvatar;

Adding Players

Present the player selector to add a player to the session:

public async void OnAddPlayerButtonPressed()
{
    try
    {
        bool playerAdded = await BoardSession.PresentAddPlayerSelector();

        if (playerAdded)
        {
            Debug.Log("New player added to session");
            // playersChanged event will fire with updated list
        }
        else
        {
            Debug.Log("Player selector dismissed");
        }
    }
    catch (InvalidOperationException e)
    {
        Debug.LogError($"Failed to present player selector: {e.Message}");
    }
}

Note: Only one player selector can be open at a time. Attempting to open another throws an exception.

Add player selector

Replacing Players

Replace or remove an existing player:

public async void OnReplacePlayerPressed(BoardSessionPlayer player)
{
    try
    {
        bool replaced = await BoardSession.PresentReplacePlayerSelector(player);

        if (replaced)
        {
            Debug.Log("Player replaced or removed");
        }
    }
    catch (InvalidOperationException e)
    {
        Debug.LogError($"Failed to replace player: {e.Message}");
    }
}

Replace Selector Behavior

The selector options change based on how many Profile players are in the session:

When replacing the only Profile in the session:

  • No “Remove player” button appears
  • No Guest option is shown
  • The player can only be replaced with another Profile

Replace selector when replacing the only Profile

When there are multiple Profiles in the session:

  • “Remove player” button appears in the top-right corner
  • Guest option is available alongside other Profiles
  • The player can be replaced, removed, or swapped with a Guest

Replace selector with multiple Profiles

This behavior ensures the session always has at least one Profile player. The native selector enforces this constraint automatically.

Note: Only one player selector can be open at a time. Attempting to open another throws an InvalidOperationException.

AI Players

Board provides UI for users to add AI players to a session, but the game is responsible for all AI behavior. The SDK does not provide any AI logic. Instead, it gives your game a way to register the AI difficulty levels or play styles it supports, and Board surfaces those options in the player selector alongside profiles and guests.

Registering AI Types

Call BoardSession.SetAIPlayerTypes() at startup to register the AI options your game supports. Each BoardAIPlayerType has a display name and optional description that appear in the player selector:

using Board.Session;

void Start()
{
    BoardSession.SetAIPlayerTypes(new BoardAIPlayerType[]
    {
        new BoardAIPlayerType { name = "Easy", description = "Plays conservatively" },
        new BoardAIPlayerType { name = "Hard", description = "Aggressive strategy" },
        new BoardAIPlayerType { name = "Master", description = "Expert-level play" },
    });
}

A maximum of 8 AI types can be registered. If your game does not call SetAIPlayerTypes(), no AI option appears in the player selector.

How AI Players Behave

AI players are ephemeral, similar to guests. They do not have a persistent profile and do not carry over between sessions. When the user selects an AI type from the player selector, Board creates an AI player with a distinct avatar and adds it to the session like any other player.

The key difference is the aiTypeIndex property, which tells your game which AI type was selected. Use this to drive your game’s AI logic:

foreach (var player in BoardSession.players)
{
    if (player.type == BoardPlayerType.AI)
    {
        int typeIndex = player.aiTypeIndex; // 0 = Easy, 1 = Hard, 2 = Master (from example above)
        // Use typeIndex to select the appropriate AI behavior in your game
    }
}

For non-AI players, aiTypeIndex returns -1.

Filtering AI Types in the Player Selector

You can control which AI types appear when opening the player selector. Both PresentAddPlayerSelector() and PresentReplacePlayerSelector() accept an optional aiTypeIndices parameter:

// Show only Easy and Hard options (indices 0 and 1)
await BoardSession.PresentAddPlayerSelector(new int[] { 0, 1 });

// Show all registered AI types (default)
await BoardSession.PresentAddPlayerSelector(null);

// No-parameter overload also shows all AI types
await BoardSession.PresentAddPlayerSelector();

This is useful if certain AI types should only be available in specific game modes.

AI Players in Save Games

AI players are stored in save game metadata just like other players. When loading a save, BoardSaveGamePlayer.aiTypeIndex preserves which AI type was active. Your game should use this to restore the correct AI behavior for that slot.

Resetting the Session

Reset players to the initial state (active profile only):

public void OnResetPlayersPressed()
{
    bool success = BoardSession.ResetPlayers();

    if (success)
    {
        Debug.Log("Players reset to initial state");
    }
}

Best Practices

  1. Use playerId for persistent data - Player IDs persist across sessions for the same profile. Use them for high scores, preferences, and unlocks.
  2. Use sessionId for in-game state - Session IDs are only unique within the current session. Use them for tracking player state during gameplay.
  3. Subscribe to playersChanged - React to players joining, leaving, or being replaced mid-session
  4. Handle guest replacements - When loading a save, deleted profiles are replaced with guests. The guest keeps the original sessionId but gets a new playerId.
  5. Register AI types early - Call SetAIPlayerTypes() before presenting the player selector so AI options are available from the start.

See Also