Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Azure for Game Developers Part 3: LiveOps and Analytics with the Microsoft Game Stack

0.00/5 (No votes)
12 Oct 2021 1  
In this article we explore how to use PlayFab to add events and gather data from our game for LiveOps and Analytics.
Here we take the game we deployed in the previous article and instrument it – using PlayFab Analytics and PlayFab Experiments – in ways that will help us gather the kind of data needed to power our game’s LiveOps journey.

Microsoft Game Stack is a collection of tools and services, including tools like Microsoft Azure, PlayFab, Xbox Services, and Visual Studio. Game developers of all sizes, from indie studios to AAA teams, can use these tools to build and launch amazing games. Once a game is deployed, it’s challenging to know what features or aspects of the game should be improved — unless you can measure them. Building this understanding is the heart of the LiveOps approach to managing a game.

In this article, we’re going to add custom events and instrumentation using PlayFab Analytics and PlayFab Experiments to the snake game from the previous part of this series. We’ll see how this data can become part of the game’s LiveOps journey.

Requirements

To follow along with this guide, you’ll need a GitHub account, a PlayFab account, and the following software installed on your computer:

You’ll also need a clone of the snake game. Follow the steps in the previous part of this series to clone it to your computer and run it locally.

Configuring the Game with PlayFab

The first thing we need to do to start using PlayFab is log in and create a studio. We’ll do this by adding a name and choosing PlayFab as the Authentication Provider.

Creating the studio will create a placeholder game title for you called My Game. Take note of the ID in the game title and copy it somewhere, as we’ll use that ID in the PlayFab SDK.

Adding Custom Anonymous Game Sessions

Next, let’s start tracking unique game sessions using PlayFab’s JavaScript SDK.

Open the project with Visual Studio Code and import the PlayFab SDK to the game page by adding the following code snippet inside the <head> tag in "app/views/game.html":

JavaScript
<script src="https://download.playfab.com/PlayFabClientApi.js"></script>

The <head> tag should look like this:

HTML
<html>
    <head>
        <title>Snake</title>
        <link rel="stylesheet" type="text/css" href="css/global.css">
        <link rel="stylesheet" type="text/css" href="css/game.css">
        <link rel="stylesheet" type="text/css" href="css/settings.css">
        <script src="https://download.playfab.com/PlayFabClientApi.js"></script>
    </head>
    <body>
        <a id="top"></a>
...

Then open the "public/js/main.js" file and add this code based on PlayFab’s JavaScript SDK example HTML file to the bottom of the page, below the game controller. Set the id variable to your PlayFab game’s title ID:

JavaScript
PlayFabLogin();

function CreateGUID()
{
    // http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {var r = Math.random()*16|0,v=c=='x'?r:r&0x3|0x8;return v.toString(16);});
}

function PlayFabLogin()
{
    var id = "YOUR-TITLE-ID";
    var GUID = localStorage.userId ? localStorage.userId : CreateGUID();

    if( !id || id == "" )
    {
        console.log( "TitleId cannot be null" );
        return;
    }
    else if( typeof PlayFab == 'undefined' ) // make sure we have the SDK prior to calling / setting
    {
        console.log( "The PlayFab SDK could not be found. Double-check your script sources" );
        return;
    }

    // save these values locally to ease use
    localStorage.userId = GUID;
    localStorage.titleId = id;

    // save title id
    PlayFab.settings.titleId = id;

    // build http request object for LoginWithCustomId
    var LoginWithCustomIdRequest = {};
    LoginWithCustomIdRequest.TitleId = id;
    LoginWithCustomIdRequest.CustomId = GUID;
    LoginWithCustomIdRequest.CreateAccount = true;

    console.log( "Logging into PlayFab..." );
    PlayFabClientSDK.LoginWithCustomID( LoginWithCustomIdRequest, ( response, error ) => {
        if( error )
        {
            console.log( error );
        }
        else
        {
            // display account details
            var result = response.data;
            var status = "Player: " + result.PlayFabId + " Session ticket: " + result.SessionTicket;
            console.log( status );
        }
    });
};

Now if you run the snake game locally and open it at http://localhost:3000, the login should show up on the PlayStream Monitor page in the PlayFab dashboard.

Reporting Custom Game Events

Next, let’s instrument our code for a variety of events so that we can see this info in the PlayFab dashboard. We’ll see this on top of the default events that are automatically tracked by PlayFab.

For example, if you’d like to add a simple event in the client-side web page, you can add this piece of code inside a successful PlayFabLogin to call WriteTitleEvent. This accepts a JSON object as its parameter and only requires an EventName field, which we will name "test_event":

JavaScript
PlayFabClientSDK.WriteTitleEvent( {
    EventName: "test_event",
}, ( response, error ) => {
    if( error ) {
        console.log( error );
    }
    else {
        console.log( response );
    }
});

Adding this event with the login function makes it show up with the login events in PlayStream:

Let’s also add some events in the backend service. We need a server-side secret key for the title, so open the Title settings page from the PlayFab dashboard and navigate to Secret Keys and locate the Secret key on the page, or create one if you don’t have one.

Add the PlayFab Node.js SDK to the snake game from a terminal window:

npm install playfab-sdk

Open "app/services/player-service.js" and insert the following PlayFab configuration near the top of the file immediately after the other require calls. Set it to your Title ID and the Secret Key.

JavaScript
const { PlayFab, PlayFabServer } = require( "playfab-sdk" );
PlayFab.settings.titleId = "YOUR-TITLE-ID";
PlayFab.settings.developerSecretKey = "YOUR-SECRET-KEY";

Then let’s add a few WriteTitleEvent calls inside events that we’d like to track, such as "change_color" in the changeColor function, or the changePlayerName function:

JavaScript
changeColor(socket) {
    const player = this.playerContainer.getPlayer(socket.id);
    const newColor = this.colorService.getColor();
    this.colorService.returnColor(player.color);
    player.color = newColor;
    this.playerStatBoard.changePlayerColor(player.id, newColor);
    socket.emit(ServerConfig.IO.OUTGOING.NEW_PLAYER_INFO, player.name, newColor);
    this.notificationService.broadcastNotification(`${player.name} has changed colors.`, newColor);

    PlayFabServer.WriteTitleEvent( {
        EventName: "change_color",
        Custom: {
            "Name": player.name
        }
    }, ( response, error ) => {
        if( error ) {
            console.log( error );
        }
        else {
            console.log( response );
        }
    });
}

Now when you run the game server and try changing the color or the player name, you’ll see the events show up in real time on the PlayStream interface.

Using PlayFab Experiments

Now that we can view the analytics data in real time, let’s take a quick look at how we can use PlayFab Experiments to run various A/B tests across our players without deploying new code each time.

PlayFab Experiments makes it very easy to run these tests because it handles all of the user segmentation and assignment for us. All we need to do is to use the configuration data from PlayFab at login time and adjust the game according to the data.

In the PlayFab dashboard, go to Experiments and create a new experiment called "Color Test." For the Control Variant, add a Control Variable named "Color" and set the value to "red." Add a similar Treatment Variable, also named "Color", to a Treatment Variant, and set this value to "blue."

After that, scroll to the bottom and click Run Now to start the experiment right away. In a few minutes, you’ll see the assigned variant and variable as part of the data returned from the login.

These experiment variables are located in the TreatmentAssignment field, and you can access them like this inside "public/js/main.js":

JavaScript
PlayFabClientSDK.LoginWithCustomID( LoginWithCustomIdRequest, ( response, error ) => {
    if( error )
    {
        console.log( error );
    }
    else
    {
        // display account details
        var result = response.data;
        console.log( result.TreatmentAssignment );
        console.log( result.TreatmentAssignment.Variables );
        if( result.TreatmentAssignment.Variables.length > 0 ) {
            document.body.style.background = result.TreatmentAssignment.Variables[ 0 ].Value;
        }
    }
});

And that’s it! Depending on the variant, your game page’s background should now either be red or blue instead of black. It’s easy to imagine this being used for experiments with many other properties of the game as well, such as difficulty levels and food scores.

Once the experiment period ends, the generated experiment report can help us decide which option worked best, using real player data.

What’s Next?

Awesome! That wraps up this series on building multiplayer games with the Microsoft Game Stack. You now have the tools and knowledge to configure and view live analytics data from your game and to run experiments to make future decisions based on the data.

We hope you enjoyed following along this series, learning to use the Microsoft Game Stack to build and deploy game servers at a global scale, and seeing a little bit of what could be possible through player and game analytics at that scale.

Happy game development!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here