PlayFab Unity


Introduction

Every great game has a good backend at it’s core. PlayFab provides an elegant yet powerful solution. The intent of this page is to document my progress in learning to use it and to provide direction for it’s implementation.

This document is a work in progress.


What is PlayFab backend?

PlayFab is a service provided by Microsoft to help developers implement cross-platform multiplayer functionality to video games such as:

  • Analytics – “Gather and view title statistics”
  • User Authentication – “Login through various platforms”
  • Title Specific Data Storage – “Inventory, purchases, profile information, friends list”
  • Party / Group – “Friend grouping”
  • Chat / VoIP – “Communications”
  • Matchmaking / Lobby – “Multiplayer queues”
  • Virtual Machine Game Servers – “Dynamic game server hosting”

PlayFab saves time and puts functionality in the hand of the developer.


Resources


Content

*Indented listings are still being researched*


Setup

PlayFab has a very detailed article about the subject which can be accessed here:

PlayFab Unity3D initial setup


Login

Once the SDK/Editor Extensions have installed , the first step is to setup some form of login behaviour to the PlayFab service as every subsequent part of PlayFab requires the user to be logged in.

There are multiple ways of authenticating the user to the service. The first ones shown in the documentation is to login with one of the anonymous login mechanisms. These include CustomID, Android and IOS. Since these are essentially identical, their respective documentation will be linked at the bottom of this section.


Login with CustomID Example

using PlayFab;
using PlayFab.ClientModels;

private void Start()
{
    LoginWithCustomID();
}

private void LoginWithCustomID()
{
    var request = new LoginWithCustomIDRequest {
     CustomId = SystemInfo.deviceUniqueIdentifier,
     CreateAccount = true,
     InfoRequestParameters = new GetPlayerCombinedInfoRequestParams
     {
       GetPlayerProfile = true
     }
};

  PlayFabClientAPI.LoginWithCustomID(request, OnLoginSuccess, OnLoginFailure);
}

private void OnLoginSuccess(LoginResult result)
{
     Debug.Log("Successful login");
}

private void OnLoginFailure(PlayFabError error)
{
     Debug.Log("Login attempt has failed");
     Debug.Log(error.GenerateErrorReport());
}

PlayFab works by sending requests and gathering results. We use these to transmit and receive data from their API. Here we intend to authenticate a user, we “request” access. In “LoginWithCustomID()”, we create a variable to hold said request. Since there are multiple choices of requests and for simplicity, we use the var keyword and name it “request”. See line 11 in example above.

We then instantiate the request using the desired type, in our case a “LoginWithCustomIDRequest“. PlayFab provides us with multiple different way’s to authenticate our users. For example, we can authenticate using Steam, Facebook, Google, Android and many more.

In our newly created request variable, we are able to input data to be relayed to the PlayFab API. At a minimum, the request will require a CustomId of sorts which, in our example, is “SystemInfo.deviceUniqueIdentifier“. However, if our user does not already have an account with the title, it will return an error. To avoid this, we add “CreateAccount = true” to the request. This will ensure that our users create an account with the “CustomId” if none can be found.

Lastly, when authenticating our users, we will most likely want to return some information about them to use in our game such as the display Name, friends list, title specific data and so on, all of which is provided and stored by the PlayFab Service. This can be accessed within the authentication request by using “InfoRequestParameters“. Since this is a new request in itself, we need to instantiate it using the keyword “new GetPlayerCombinedInfoRequestParams“. Through this request, we can gather the users profile, statistics, inventory and so on. In our example, we want to access the player’s display name which leads us to “GetPlayerProfile” that we will set to true. See line 16 of the above example.


SystemInfo.deviceUniqueIdentifier Side Note


We now have a request ready to be used to authenticate our user. To do this, we call up the client API using “PlayFabClientApi.*”. In our example, we follow this statement with the method “LoginWithCustomID( )” and pass along our data. This method takes in our request variable and has two callbacks that need to be implemented to deal with success or failure.

The first is success. This method must have a parameter of type “LoginResult“. This parameter will contain all the information we should need for our user. The other will be used for failures and takes a “PlayFabError” parameter.

The “LoginResult” parameter provides us quite a bit of information about our user which we can then use for our game such as the player’s profile or Entity ID / Entity Type.

* Entity ID is the ID used by PlayFab to reference the user in it’s database.
** Entity Type – Not 100% sure what this is for just yet. TBD
*** Entity Token Response

Note: CustomID, Android and IOS all can be authenticated without further steps using “SystemInfo.deviceUniqueIdentifier“. All other way’s of authentication require development accounts with the respective providers and possibly other SDK’s. More on this later.

Get Display Name Example


Extra resources

Back to Top


Party/Network/Chat

PlayFab describes this feature as Game Networking / VoIP and Chat. With this SDK, we can create “Networks” and our users can join. The user only needs a network ID and they are able to join a network. We can then send data over the network.

Intended use case

Pre, Post and in game chat/VoIP. More info to come.

Important Side Note

PlayFab Party SDK Quickstart Documentation

Before we get started, visit your Title Overview at PlayFab.com. Click on the multiplayer tab on the left and then the party tab up top. Make sure it’s enabled.

After installing the SDK, navigate to the prefabs folder and drag the multiplayer manager into your scene.


User Interface Example


Back to code

using System.Text;
using UnityEngine;
using UnityEngine.UI;
using PlayFab;
using PlayFab.Party;
using PlayFab.ClientModels;
using TMPro;

void Start()
{
    UI_LoginInputField.text = SystemInfo.deviceUniqueIdentifier;
}

private void Update()
{
    if (Input.GetKeyDown(KeyCode.Return))
    {
        SendChatMessage();
    }
}

As with any script, we begin by adding namespaces we will need and some member variables to hold some data.

  • PlayFab.Party;
  • System.Text; – Used to access Encoding namespace which is in turn used to send data over to the PlayFab service. More on that later.
  • UnityEngine.UI; – Optional.
  • TMPro; Optional.

Member Variable Example

Scroll down to your OnLoginSuccess method. Whenever this method gets called, we know that we are authenticated to the PlayFab service.

void OnLoginSuccess(LoginResult result)
{
    Debug.Log("Successful login/account creation.");

    if(result.InfoResultPayload.PlayerProfile.DisplayName != null)
    {
        DisplayName = result.InfoResultPayload.PlayerProfile.DisplayName;
    }

    PlayFabMultiplayerManager.Get().CreateAndJoinNetwork();
    PlayFabMultiplayerManager.Get().OnNetworkJoined += OnNetworkJoined;
    PlayFabMultiplayerManager.Get().OnRemotePlayerJoined += OnRemotePlayerJoined;
    PlayFabMultiplayerManager.Get().OnRemotePlayerLeft += OnRemotePlayerLeft;
    PlayFabMultiplayerManager.Get().OnDataMessageReceived += OnDataMessageReceived;
    PlayFabMultiplayerManager.Get().OnChatMessageReceived += OnChatMessageReceived;
}

public void JoinNetwork()
{
    PlayFabMultiplayerManager.Get().JoinNetwork(UI_NetworkInputField.text);
}

The Party SDK comes preloaded with a bunch of events which are available through it’s singleton (“PlayFabMultiplayerManager” in example above). It’s important to make sure we are authenticated before making calls or we will return errors. When we call the singleton’s CreateAndJoinNetwork method, PlayFab will automatically generate a NetworkID for you that you can share with other users through various means.

private void OnNetworkJoined(object sender, string networkId)
{
    Debug.Log(networkId);
    NetworkID = networkId;
    
    UI_NetworkInputField.text = networkId;
}

private void OnRemotePlayerLeft(object sender, PlayFabPlayer player)
{
    Debug.Log($"{player} has left the network.");
}

private void OnRemotePlayerJoined(object sender, PlayFabPlayer player)
{
    Debug.Log($"{player} has entered the network.");
    var localPlayer = PlayFabMultiplayerManager.Get().LocalPlayer;
}

private void OnDataMessageReceived(object sender, PlayFabPlayer from, byte[] buffer)
{
    var text = Encoding.Default.GetString(buffer);
    Debug.Log(text);
}

private void OnChatMessageReceived(object sender, PlayFabPlayer from, string message, ChatMessageType type)
{
    Debug.Log(message);
    UI_ChatBox.text += ($"\n {from}: {message}");
}
public void SendChatMessage()
{
    string message = ($"{DisplayName}: {UI_ChatInputField.text}");
    byte[] requestAsBytes = Encoding.UTF8.GetBytes(message);
    PlayFabMultiplayerManager.Get().SendDataMessageToAllPlayers(requestAsBytes);
    UI_ChatBox.text += ($"\n {message}");
    UI_ChatInputField.text = "";
}

public void QuitApplication()
{
    Application.Quit();
}
public void Login()
{
    PlayFabLoginWithCustomID();
}

Notes for later. PlayFabMultiplayerManager methods.

Difference between SendChatMessageAPI and SendDataMessageAPI
The primary difference between those two methods is their intended use by the recipient. A chat message is intended to be printed as a message, shown to the player. A data message is, instead, meant to be raw data transferred between clients. It won’t necessarily be displayed directly to the player and is generally used for client-to-client communication and synchronization.

Back to Top


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.