Skip to main content

PlayPad compatible lobby integration guide

For asynchronous games with tournaments

Lobby scene UI contents

PlayPad lobby scene example
Example arrangement of lobby scene required contents

  1. Free space at the top of the canvas - for PlayPad provided player info panel
    • about 7~8% of canvas vertical space (140 units with 1920 units high canvas)
  2. Game logo
  3. Tournament title - from the TournamentInfo
  4. Switch Tournament button
    • (logic handled by PlayPad) shows the selection process of tournaments that the user can enter in an over-game UI
    • should be near the tournament title
    • should be represented by a custom icon (without text)
    • as a clickable button it should be green to encourage user activity
  5. Time left to close the tournament (custom icon is recommended)
  6. Number of participants in the tournament (custom icon is recommended)
  7. Tournament Rewards button
    • (logic handled by PlayPad) displays the current Tournament Rewards in an over-game UI
    • should display short prize pool summary message
    • should be represented by a custom icon
    • as a clickable button it should be green to encourage user activity
  8. Leaderboard
    • should be able to display from 0 to 6 entries (you should always have 6 slots ready to display, but depending on the received data, not all of them may be shown)
    • should display all the received entries (you won't receive more than 6)
    • entries are in ascending position order but may not be consecutive (e.g. 1, 2, 3, 25, 26, 27) - received entries are determined by PlayPad
    • if adjacent entries are not consecutive, a visual separator should be displayed between them (e.g. ". . .")
  9. All time high score of the player
  10. Play button - adjusted visually to tournament play availability, with displayed proper info label
    • with 3 possible, distinguishable states to inform the user of playing possibility:
      • Play (i.e. green) – gameplay is possible, pressing play will proceed directly, or almost directly to the gameplay
      • UserActionRequired (i.e. blue) – gameplay is possible but requires some long-lasting action that can be handled by the PlayPad (like signing in via wallet, confirming a transaction, buying entries, etc.)
      • Blocked (non-interactable button) (i.e. grey) – gameplay is not possible, and it is not fixable (the tournament is already finished, or it requires some NFT that the user does not have and cannot buy directly, etc.) with exception of the case when the tournament has not yet started
    • remember that you only should have one Play button and its state should only be determined by the most recent PlayStatusInfo you received. PlayPad SDK and PlayPad are fully responsible for handling the logic of what's behind this button, so you don't have to implement any blockchain or tournament-specific logic.
  11. Authentication in progress waiting panel
  12. Match loading waiting panel
  13. Error displaying panel - for handling unsuccessful user action resolving (i.e. canceling wallet sign) and edge cases (i.e. tournament ended when a player was resolving needed external actions)

Migration from 0.4.5 to 1.1.1

Using AsyncGameSample

As the scope of migration may be quite broad, it is recommended to use the sample in place of your old, manual lobby integration. With that, you can just focus on implementing your graphics according to your design without needing to worry about technical details.

If you use randomization

For randomization, when the tournament is not default (TournamentInfo.OwnerId is not null), you should derive the seed from TournamentInfo.Id.GetHashCode() to keep the tournament challenge uniform between all the contestants.
For default, daily ones it is best to use full randomization to make the game more surprising, fun and engaging.

Custom migration

  1. Update Elympics SDK to at least 0.14.2

  2. Update PlayPad SDK (formerly known as Elympics Lobby Package or Elympics External Communicator) to at least 1.1.1

  3. Rename all occurrences of ElympicsExternalCommunicator to PlayPadCommunicator

  4. Delete SessionManager.TryReAuthenticateIfWalletChanged or SessionManager.TryReAuthenticateIfAuthDataChanged usages

  5. Delete GameFinished usage when finishing the Gameplay

  6. Delete OnWalletConnectedChanged usages

  7. Go through all the compile errors and using IDE try auto-resolving missing using directives (and delete non-existent ones)

  8. Remove the Player Info Bar from the menu scene entirely (both UI and code)

  9. Remove the Connect Wallet button from the menu (both UI and code)

  10. Remove all the code responsible for fetching and updating the Leaderboard (UI should not be removed)

  11. Remove all the logic that adjusts the "Play button" state based on the context (like setting it to "Train" when the user is not logged in)

  12. Remove all the logic that selects the matchmaking queue based on the context (only one solo queue is needed now)

  13. If any compile error remains, it is recommended to delete the line causing it and message us about the occurrence on our developers' Discord

  14. Ensure you have the PlayPadCommunicator prefab on your lobby scene and provide references to standalone configs for its PlayPadCommunicator script. To create them go to the Project context menu, then Create->Configs->Standalone. You can also delete the old StandaloneBrowserJsConfig ScriptableObject, which is no longer used

  15. Ensure that ElympicsLobbyClient's AuthenticateOnAwakeWith is set to None

  16. On Start, find the SessionManager game object and call a method connecting to the PlayPad (but only once per game application launch) and adjusting lobby UI with provided data

    private void Start()
    {
    var sessionManager = FindObjectOfType<SessionManager>();
    OnLobbySceneLoaded(sessionManager).Forget();
    }

    private async UniTask OnLobbySceneLoaded(SessionManager sessionManager)
    {
    bool shouldHideSplashScreen = false;

    if (!sessionManager.ConnectedWithPlayPad)
    {
    await sessionManager.AuthenticateFromExternalAndConnect();
    shouldHideSplashScreen = true;
    }

    // Put here any further lobby scene configuration and UI adjustments
    . . .

    if (shouldHideSplashScreen)
    PlayPadCommunicator.Instance.GameStatusCommunicator?.HideSplashScreen();
    }

After these changes and uploading the server build you should be able to play the game now without errors. If that's not the case, please contact us on our developers' Discord.

Implementing lobby scene features
  1. To show "Authentication waiting panel" correctly, before ConnectedWithPlayPad if statement, subscribe to the events below. Remember to unsubscribe if destroying the subscribing object

    sessionManager.StartSessionInfoUpdate += ShowAuthenticationWaitingPanel;
    sessionManager.FinishSessionInfoUpdate += HideAuthenticationWaitingPanel;
  2. Use PlayPadCommunicator.Instance.LeaderboardCommunicator to set up the leaderboard UI

    • use .Leaderboard to access the leaderboard's entries, player's entry, and number of participants to display (available after AuthenticateFromExternalAndConnect)
    • use .LeaderboardUpdated event to get notified when PlayPad's leaderboard data gets updated (after leaving the gameplay scene) then adjust to it
    • [optional] use .FetchLeaderboard() to manually fetch the most recent leaderboard results from the PlayPad (meant for custom usage)
  3. Use PlayPadCommunicator.Instance.TournamentCommunicator to set up tournament UI

    • use .CurrentTournament to access the tournament's data like its name, start, and end dates, and more (available after AuthenticateFromExternalAndConnect)
    • use .TournamentUpdated event to get notified when PlayPad's tournament data gets changed then adjust to it
    • [optional] use .GetTournament() to manually fetch current tournament data from the PlayPad (meant for custom usage)
  4. Use PlayPadCommunicator.Instance.GameStatusCommunicator to set up play button visuals, availability, and functionality

    • use .CurrentPlayStatus to access the tournament's play availability status and short text to put on the button label (available after AuthenticateFromExternalAndConnect)
    • use .PlayStatusUpdated event to get notified when tournament play availability changes then adjust to it
    • use .PlayGame(...) to load a match and run the gameplay
    • [optional] use .CanPlayGame(false) to manually fetch current play availability data from the PlayPad (meant for custom usage)
  5. PlayButton should:

    • call PlayPadCommunicator.Instance.GameStatusCommunicator.PlayGame() upon click (note that PlayGameConfig's QueueName parameter is the only mandatory one)
    • try..catch around the call to handle and display potential issues
    • display match loading screen upon click (and hide it on an error)
    • change visually according to the PlayStatus
    • be non-interactable when in a Blocked state
    • use LabelInfo as displayed text
    info

    PlayPad SDK & PlayPad will take care of all the context-dependent requirements that the player has to meet to proceed with the gameplay. Corresponding UI will be displayed over your game (similar to how In-App Purchase UI could be displayed over your game in an iOS environment). So you don't have to care about what the user is doing with our (PlayPad) UI, but instead, you will be delivered a final result (which is proceeding to the game or failing with an error code)

  6. Tournament Rewards button should call PlayPadCommunicator.Instance.ExternalUiCommunicator.Display("tournament/rewards"). It is async and becomes complete after closing the corresponding over-game UI

  7. Switch Tournament button should call PlayPadCommunicator.Instance.ExternalUiCommunicator.Display("tournament/change-view") It is async and becomes complete after closing the corresponding over-game UI

  8. Use PlayPadCommunicator.Instance.LeaderboardCommunicator to set up the player's all-time high score

    • use .UserHighScore to access the player's all-time best score (available after AuthenticateFromExternalAndConnect)
    • use .UserHighScoreUpdated event to get notified when PlayPad's best score data gets updated (after leaving the gameplay scene) then adjust to it
    • [optional] use .FetchUserHighScore() to force fetch the most recent all-time best score (meant for custom usage)
  9. If you use randomization and the tournament is not default (TournamentInfo.OwnerId is not null), you should derive the seed from TournamentInfo.Id.GetHashCode() to keep the tournament challenge uniform between all the contestants.