Integrating Android Performance Tuner into your Unity game

1. Introduction

Last Updated: 2023-07-19

Why use Android Performance Tuner?

Android Performance Tuner helps you to measure and optimize your game's frame rate stability and graphical fidelity across many Android devices at scale, enabling you to deliver the best possible experience to each of your users. The Android Performance Tuner library, also known as Tuning Fork, records and aggregates live frame time information from your game, alongside your own game annotations and fidelity parameters, and uploads this data to the Play Console. This unlocks a new suite of metrics and insights in Android vitals.

d96f7a32bee6ab59.png

What you'll build

In this codelab, you're going to open a demo game made for Unity, test it, and integrate Android Performance Tuner with it. After setting up and verifying that Android Performance Tuner works, we'll show how to upload the game to the Play Store and get access to the new performance insights provided by Android Performance Tuner in the Play Console.

What you'll learn

  • How to add and set up Android Performance Tuner for your game.
  • How to verify that Android Performance Tuner works properly and inspect the insights shown in the Play Console.

What you'll need

  • Unity 2020 LTS installed on your computer.
  • An Android device, connected to your computer, that has Developer options and USB debugging enabled. You will run the game on this device.
  • A Google Developer account, and access to the Play Console to upload your game and to view Android vitals.

2. Opening Boat Attack with Unity

Get Boat Attack from GitHub

Follow these steps:

  • Ensure you have git lfs installed.
  • Clone the git repo using the command line (or your favorite git client): git clone https://github.com/Unity-Technologies/BoatAttack.git
  • Check out the branch corresponding to your Unity version using the command line: git checkout release/2020.3-LTS

Open Boat Attack with Unity 2020 LTS

Open the Unity Hub and choose Open > Add project from disk:

Choose the folder where you extracted the archive or cloned the Git repository.

The project will be added to the list of projects. Select an install of Unity 2020 LTS as the version of Unity to use with this project. This codelab was tested with Unity 2020 LTS. Other versions of Unity may require additional work not covered by this codelab.

Click the BoatAttack Unity editor version in the Editor Version column. Choose your installed version of Unity 2020 LTS and select Android as the platform. You can later switch to another platform, but Unity will have to re-import all of the assets, which can take some time.

ec94231ea4f07433.png

When you have the Android platform selected for the project, click on the project to open it. If you are asked to downgrade or upgrade the project, this means that your Unity version is different from the one that was used to create the project.

When Unity starts, you'll see the editor with a welcome window:

ee2046703c176f89.png

Close the Gameplay Ingredients tip window. In the Boat Attack welcome window, choose Open main_menu. You can then close this window too. If you don't see this window, click File > Open Scene and navigate to Assets > Scenes > main_menu.unity.

If you want to see the game in action, click the play button:

6bdbbfcae30e0d20.png

Click Race.

702d63eecdd35e77.png

Click Spectator.

d9c791977f87de76.png

Click Race.

376fa3bc1b05e793.png

Wait for the game to load. The game will run in the editor. Because this is a demo, the boat is controlled by the AI.

6ff0d453dab5c047.png

Now that you have the game open and running on your computer, let's try it on an Android device and then add Android Performance Tuner.

3. Try the game on a device

Before integrating Android Performance Tuner, it's a good idea to get familiar with the game and run it on an Android device.

Open the Build Settings

In the File menu, choose Build Settings. Under Platform, select Android. Then click Switch Platform.

cf673361789a85ca.png

Unity will re-import the assets for Android if it was not selected, which can take a bit of time.

Remove the demo scene from the build

To reduce the game size and the build time, we'll remove the demo_Island scene from the build. Clear the checkbox for the demo_island scene.

f9182897009ffd37.png

By default, the main_menu and level_Island scenes are included. Make sure the main_menu scene has a value of 0; otherwise, drag and drop it to the top of the list.

Ensure arm64 architecture is activated

To make sure the game is running at the highest speed on Android devices with 64-bit processors, make sure the game binaries are built with support for arm64. Open the Player Settings:

fe88f2f93795443c.png

The settings are shown in a separate window. Under Settings for Android, click Other Settings:

83d79d8645fb4916.png

Scroll down in the settings. Under Target Architectures, ensure the ARM64 and ARMv7 checkboxes are selected:

7e5a3abd08ef4524.png

You can now close this window.

Build addressables

Before building the game, you need to build Unity addressables.

Open Window > Asset Management > Addressables > Groups.

7e88d1ad2e311b2.png

In the Addressables Groups window, choose Build > New Build > Default Build Script:

8e99361cafa3bc10.png

Wait for Unity to build the Addressables assets.

When it's done, you're ready to build and run the game on an Android phone.

Build and run the game

Connect your Android device to your computer and be sure to have the Build Settings window opened. Make sure your device has the developer options and USB Debugging enabled.

When connected, you can click the Refresh button *—*next to the Run Device dropdown menu— then click on the dropdown and find your device.

f0a02de254b3589c.png

Once you've confirmed that your device is properly connected, you can keep the Default device option selected.

Click the Build And Run button. You'll be asked where to save the generated APK file on your computer. Choose a folder and enter a name like "BoatAttackDemo".

If the game doesn't build, go to Unity > Preferences > External Tools and check that all of the Android tools are installed and that no warning is shown:

8fcdacc20208f57d.png

Unity will now compile the game. This can again take a bit of time. At the end, the game will be installed on your device and started.

4. Get an API key for Android Performance Tuner

Enable "Android Performance Parameters API" on Google Cloud Platform

Before integrating Android Performance Tuner in your project, you need to get an API key for it. Android Performance Tuner will send performance data to the Google Play Console APIs, which must be able to identify your game.

  1. Create a new Cloud project in the Cloud Console:
  2. Enter a name for your Cloud project and click Create.
  3. Search for "Android Performance Parameters API" in the Marketplace.
  4. Enable the API.

Create an API key

The library is enabled, let's now create the API key:

  1. Go to API & Services, then Credentials from the menu.
  2. Click Create Credentials and choose API Key.
  3. From the API key created window, copy the value of the key and store it in a safe place.
  4. Click on Restrict Key.
  5. Enter a name for the key. Choose something that will remind you that it is linked to your game and Android Performance Tuner (for example, BoatAttack with Performance Tuner API key). d63812118a0bd069.png
  6. Under API restrictions, choose Restrict key and select Android Performance Parameters API: 6d23b08d636689ca.png
  7. Click Save to finish.

Now that you have the API key, copy it and keep it somewhere as you will need it to set up the Android Performance Tuner Unity plugin.

5. Add and set up the Android Performance Tuner

You will now install the Android Performance Tuner Unity plugin in the game.

Download and install the plugin

Download the Android Performance Tuner Unity plugin from GitHub and save it somewhere on your computer.

Choose the .unitypackage file for android-performance-tuner. Make sure the version number is 1.5.0 or higher. This file is a Unity Package that you can import in your project. In the Unity Assets menu, choose Import Package > Custom Package...

729bde4c222e5bbb.png

Choose the unitypackage file that you just downloaded. If asked which file to import, choose to import all the files.

Set the API key and explore the plugin configuration

When the Android Performance Tuner plugin is installed, you can open its configuration from the Window > Android Performance Tuner > Setup menu item.

124e133ff8a1dafe.png

The first tab shown in the window contains a field for the API Key. Paste your API key here:

c2044acbf4d82402.png

The other tabs allow you to specify annotations and fidelity parameters.

  • An annotation gives contextual information about what your game is doing when a frame is recorded (for example, the current level, whether a scene is loading, or any other state you think is relevant).
  • A fidelity parameter is a parameter that can be modified to adjust the game quality. For example, this can be the level of detail of 3D models, texture resolution, the game rendering resolution, the number of particles on screen, etc.

In this codelab, you won't define any custom annotations or fidelity parameters. The Android Performance Tuner Unity plugin will record the current scene name as an annotation, and the active quality settings, defined in the Unity settings, as a fidelity parameter.

Enable Optimized Android Frame Pacing and VSync

Open the Player Settings (from the Build Settings window).

Under Settings for Android in the Resolution and Presentation section, make sure to enable Optimized Frame Pacing:

ef3cdd3ac05b2cd.png

This will enable the Android Frame Pacing library for your game. Android Performance Tuner will use it to measure the performance of your game, including more in-depth measures compared to what Unity alone will report if you don't select this option.

From the Player Settings, select the Quality tab and find the VSync Count menu. Use any selection (except Don't Sync). This enables more precise measurements in conjunction with the Android Frame Pacing library.

cdd682549368591b.png

Initialize Android Performance Tuner in your game

To enable Android Performance Tuner to instrument your game and send the gathered data to Play Console APIs, you need to initialize it. You will do that by creating a new script called GamePerformanceManager. You will use the existing AppSettings script to call GamePerformanceManager and initialize Android Performance Tuner when started.

  1. In the Project tab, navigate to Scripts > GameSystem.

    3f74634497ec53be.png
  2. Click the + button and choose C# Script.

    3b45e8b3012d927b.png
  3. Enter GamePerformanceManager as the script name: d68dd365e72a0f1a.png
  4. Double-click the GamePerformanceManager script. Inside, instantiate AndroidPerformanceTuner and create an Initialize method. This method initializes the library by calling its Start method. Copy all of the following code into the new class
using Google.Android.PerformanceTuner;
using System.Collections;
using UnityEngine;

public class GamePerformanceManager
{
    AndroidPerformanceTuner<FidelityParams, Annotation> tuner =
        new AndroidPerformanceTuner<FidelityParams, Annotation>();

    public IEnumerator Initialize()
    {
        yield return new WaitForEndOfFrame(); // Needed to make sure Vulkan backend is fully ready, after the first frame.
        ErrorCode startErrorCode = tuner.Start();
        Debug.Log("Android Performance Tuner started with code: " + startErrorCode);

        tuner.onReceiveUploadLog += request =>
        {
            Debug.Log("Telemetry uploaded with request name: " + request.name);
        };
    }
}
  1. Open the AppSettings script. You will use it to instantiate the GamePerformanceManager and call its Initialize method. Add a private gamePerformanceManager field and add the Start method to call its Initialize method:
using System;
// ...

namespace BoatAttack
{
    [ManagerDefaultPrefab("AppManager")]
    public class AppSettings : Manager
    {
        // ...
        private GamePerformanceManager gamePerformanceManager = new GamePerformanceManager();
        
        // ...
        public IEnumerator Start()
        {
            yield return StartCoroutine(gamePerformanceManager.Initialize());
        }

        // ...
  1. This is enough to get Android Performance Tuner started and your game instrumented. We've added logs when Android Performance Tuner is started and when telemetry is uploaded to the Google Play Console APIs so that it's easier to verify that Android Performance Tuner works.

Reduce the interval between telemetry upload for testing

As we're still implementing the library in the project, it's a good idea to reduce the time between the uploads of the telemetry. By default, this time is set to a large interval so that the game is not making too many requests to the APIs, which is especially important for users that don't have a mobile data plan that includes unlimited data. This also avoids draining the battery.

In the case of this codelab, you can reduce this interval to make it easier to verify the proper uploading of the telemetry.

  1. Open the Android Performance Tuner settings by clicking Window > Android Performance Tuner > Setup in the menu.
  2. Choose Instrumentation Settings, then click Use advanced settings.
  3. Enter 0.5 in the Intervals (minutes) field: 1fd3b402d319e5ac.png

This will make Android Performance Tuner upload the telemetry every 30 seconds.

You now have Android Performance Tuner integrated, set up and initialized in your game. In the next section, we'll confirm proper integration by running the game on a device and checking the logs.

6. Verify the proper integration of Android Performance Tuner

Check that Android Performance Tuner starts properly

To confirm that Android Performance Tuner is properly integrated, connect your device to your computer and then build and run the game. In Unity, choose File > Build And Run. Be sure that Android is selected as the current platform; otherwise, switch to it in Build Settings.

While your game is launching on your phone, open a terminal on your computer and launch adb logcat:

adb logcat

Wait for the game to compile and run on your device.

In the output of adb logcat, search for TuningFork (Tuning Fork is the internal name of the Android library):

02-03 16:55:45.103 10511 10536 I TuningFork: Got settings from tuningfork/tuningfork_settings.bin
02-03 16:55:45.103 10511 10536 I TuningFork: Using local file cache at /data/user/0/com.Unity3d.BoatAttackDay/cache/tuningfork
02-03 16:55:45.105 10511 10536 I TuningFork: OpenGL version 3.2
02-03 16:55:45.105 10511 10536 I TuningFork: TuningFork.GoogleEndpoint: OK
02-03 16:55:45.106 10511 10611 I TuningFork: Creating directory /data/user/0/com.Unity3d.BoatAttackDay/cache/tuningfork
02-03 16:55:45.106 10511 10536 I TuningFork: TuningFork Settings:

[...]

02-03 16:55:45.107 10511 10536 I TuningFork: TuningFork initialized
02-03 16:55:45.107 10511 10536 I UnityTuningfork: Swappy backend: 1
02-03 16:55:45.107 10511 10536 I TuningFork: Creating directory /data/user/0/com.Unity3d.BoatAttackDay/cache/tuningfork/V1
02-03 16:55:45.110 10511 10613 I TuningFork: OpenGL version 3.2
02-03 16:55:45.110 10511 10613 I TuningFork:Web: Connecting to: https://performanceparameters.googleapis.com/v1/applications/com.Unity3d.BoatAttackDay/apks/1:generateTuningParameters

If you made a mistake while setting up Android Performance Tuner, like forgetting to set the API key, you should see an error in the initialization logs. For example:

02-03 16:49:44.970  8815  8831 I TuningFork: Got settings from tuningfork/tuningfork_settings.bin
02-03 16:49:44.971  8815  8831 I TuningFork: Using local file cache at /data/user/0/com.Unity3d.BoatAttackDay/cache/tuningfork
02-03 16:49:44.972  8815  8831 I TuningFork: OpenGL version 3.2
02-03 16:49:44.972  8815  8831 W TuningFork.GE: The API key in Tuning Fork TFSettings is invalid
02-03 16:49:44.972  8815  8831 E TuningFork: TuningFork.GoogleEndpoint: FAILED
02-03 16:49:44.973  8815  8831 I Unity   : Tuningfork started with code: BadParameter

Check that Android Performance Tuner is uploading telemetry

If you see TuningFork initialized in the logs, wait a bit more and look for logs indicating that telemetry is being uploaded:

02-03 16:58:00.552 10511 10611 I TuningFork:Web: Connecting to: https://performanceparameters.googleapis.com/v1/applications/com.Unity3d.BoatAttackDay/apks/1:uploadTelemetry
02-03 16:58:00.898 10511 10611 I TuningFork:Web: Response code: 200
02-03 16:58:00.898 10511 10611 I TuningFork:Web: Response message: OK
02-03 16:58:00.899 10511 10611 I TuningFork.GE: UPLOAD request returned 200 {}

Search in the logs for Connecting to, followed by the response code a few lines after.

Now that we've confirmed that Android Performance Tuner is running and can properly upload the data from the game, we'll add an in-game annotation to tell the Android Performance Tuner when the game is loading. This will avoid recording performance at this moment - which is expected to be poor. We'll then build and upload the game to the Play Store, distribute it to testers and verify that insights are shown in the Vitals section of the Play Console.

7. Add loading time recording functions

It's important to record when your game is performing loading events for two reasons:

  1. To avoid polluting your frame time data while loading.
  2. To analyze load times to see when and where load times are longer than acceptable.

A loading event can have an associated annotation (defined in the same way as frame time annotations) and metadata. As a single loading period seen by the user may contain several loading events, all loading events must be part of a loading group. Only one loading group can be active at a time. Loading groups and events are identified by handles that are used by the Stop functions to end the recordings.

  1. Create a new public method in GamePerformanceManager, called StartRecordingLoadingGroup:
public class GamePerformanceManager
{
    // ...

    public ulong StartRecordingLoadingGroup()
    {
        LoadingTimeMetadata groupMetadata = new LoadingTimeMetadata()
        {
            state = LoadingTimeMetadata.LoadingState.InterLevel,
            source = LoadingTimeMetadata.LoadingSource.UnknownSource
        };
        // The metadata and annotation are currently not used by the
        // Play backend but only the annotation can be set to null.
        Result<ulong> result = tuner.StartLoadingGroup(groupMetadata, null);
        return result.value;
    }

  1. Create a new public method in GamePerformanceManager, called StartRecordingLoadingEvent:
public class GamePerformanceManager
{
    // ...

    public ulong StartRecordingLoadingEvent(int sceneIndex)
    {
        LoadingTimeMetadata sceneLoadingMetadata = new LoadingTimeMetadata()
        {
            // Any fields that aren't relevant to your needs can be zero.
            state = LoadingTimeMetadata.LoadingState.InterLevel,
            source = LoadingTimeMetadata.LoadingSource.UnknownSource,
            compression_level = 0,
            network_connectivity = 0,
            network_transfer_speed_bps = 0,
            network_latency_ns = 0
        };
        Annotation annotation = new Annotation() {Scene = (Scene) (sceneIndex + 1)};
        // Start recording loading time.
        Result<ulong> result = tuner.StartRecordingLoadingTime(sceneLoadingMetadata, annotation);
        return result.value;
    }
  1. Create a new public method in GamePerformanceManager, called StopRecordingLoadingEvent:
public class GamePerformanceManager
{
    // ...

    public void StopRecordingLoadingEvent(ulong handle)
    {
        tuner.StopRecordingLoadingTime(handle);
    }

The recorded event is uploaded at the next session flush.

  1. Create a new public method in GamePerformanceManager, called StopRecordingLoadingGroup:
public class GamePerformanceManager
{
    // ...

    public void StopRecordingLoadingGroup(ulong handle)
    {
        tuner.StopLoadingGroup(handle);
    }
  1. Open the AppSettings script, where you previously added the GamePerformanceManager field and called its Initialize method.
  2. Add two ulong variables that will store the handles of the loading group and loading event.
using System;
// ...

namespace BoatAttack
{
    [ManagerDefaultPrefab("AppManager")]
    public class AppSettings : Manager
    {
        // ...
        public ulong groupHandle;
        public ulong eventHandle;
  1. Find the LoadScene(int buildIndex, LoadSceneMode mode) method and add calls to StartRecordingLoadingGroup and StartRecordingLoadingEvent. Save their results in the corresponding handles. Then, find the CleanupLoadingScreen method and add calls to StopRecordingLoadingEvent and StopRecordingLoadingGroup passing the stored handles:
using System;
// ...

namespace BoatAttack
{
    [ManagerDefaultPrefab("AppManager")]
    public class AppSettings : Manager
    {
        // ...
        public static void LoadScene(int buildIndex, LoadSceneMode mode)
        {
            Instance.groupHandle = Instance.gamePerformanceManager.StartRecordingLoadingGroup();
            Instance.eventHandle = Instance.gamePerformanceManager.StartRecordingLoadingEvent(buildIndex);
            // ...
        }

        // ...

        private void CleanupLoadingScreen()
        {
            Instance.gamePerformanceManager
                .StopRecordingLoadingEvent(Instance.eventHandle);
            Instance.gamePerformanceManager
                .StopRecordingLoadingGroup(Instance.groupHandle);
            // ...
        }

With this, Android Performance Tuner will be able to know when a loading event is in progress. During loading events, the frame times are not recorded.

You can now build and upload the game to the Play Store, distribute it to testers and verify that insights are shown in the Vitals section of the Play Console.

8. Visualize data with the monitoring app (optional)

The monitoring app is a tool part of Android Game SDK. You can redirect the performance data collected by the Android Performance Tuner to this app running on your device, to see in real time, what is collected. It's a useful debugging tool.

Build the monitor app

The monitor app must be built before being used. Ensure that you have Android Studio installed. If that's not the case, download the latest version from the Android Developer website:

You also need to download the source code of the Android Game SDK. Ensure you have a git client installed (either the git command line or a GUI client).

Clone the content of the Game SDK:

git clone https://android.googlesource.com/platform/frameworks/opt/gamesdk

Compile the monitoring app. Open Android Studio. In the welcome window, choose Import project (Gradle, Eclipse ADT, etc.).

27d916394474814a.png

Navigate to the folder gamesdk that was created. Choose src > tuningfork > tools > TuningForkMonitor.

16454af85bdea995.png

Android Studio will open the project:

786ced03c12d587e.png

The app is a Kotlin Android app. If you're interested in making apps with Kotlin on Android, read more about it on the Android Developers website.

Wait for the project to sync. Connect your device and click the Run button. The run button is displayed next to the device name in the top toolbar.

496c4669bf2cfe86.png

The app will now run on device and will wait for a connection from a game:

1b06081cbff3fc12.png

You will now slightly modify the game configuration to connect to this monitoring application.

Set up the game to connect to the local monitoring app

Let's now build the game in Unity so that it connects to the monitoring app.

In the Initialize method of GamePerformanceManager, add just before tuner.Start() a line to enable the local endpoint: tuner.EnableLocalEndpoint()

using Google.Android.PerformanceTuner;
using UnityEngine;

public class GamePerformanceManager
{
    // ...

    public IEnumerator Initialize()
    {
        yield return new WaitForEndOfFrame(); // Needed to make sure Vulkan backend is fully ready, after the first frame.
        tuner.EnableLocalEndpoint(); // For local testing.
        ErrorCode startErrorCode = tuner.Start();
        // ...
    }
}

Build the game as a development build

You now need to build and run the game using:

  • The Development Build option
  • With cleartext http communication enabled in the AndroidManifest.xml file

To enable the http communication, in your Projects Assets, create a folder called Plugins, and create another folder called Android:

16c9133cfedf5828.png

3d3ce146436f7cf1.png

Create a new file called AndroidManifest.xml inside this folder. Inside this file, paste the following content:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools">
  <application android:usesCleartextTraffic="true" android:isGame="true">
    <activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector" android:screenOrientation="landscape" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:hardwareAccelerated="false">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
      </intent-filter>
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
    </activity>
  </application>
</manifest>

Most of the content of this file is the default elements generated by Unity. The code above adds android:usesCleartextTraffic="true" in the application element, to indicate that you expect your application to use cleartext HTTP.

You can now open again the Build Settings window. Check Development Build:

159fe8314cd8f61a.png

Click Build And Run to build and launch the game on your device. Make sure you have the Tuning Fork Monitor app running.

Inspect performance data from the monitoring application

Once the game is started, make sure to run it for one minute to get some data reported. Check in the logs that you can see that localhost:9000 (the address of the local server running on the device) is reported.

05-14 14:03:26.226 11087 11170 I TuningFork:Web: Connecting to: http://localhost:9000/applications/com.Unity3d.BoatAttackDay/apks/1:uploadTelemetry
[...]
05-14 14:03:26.323 11087 11170 I TuningFork:Web: Response code: 200
05-14 14:03:26.323 11087 11170 I TuningFork:Web: Response message:
05-14 14:03:26.323 11087 11170 I TuningFork.GE: UPLOAD request returned 200{}

Switch from the game to the monitoring app on your device, and you'll see the game listed in the list of applications:

b5670b4161f29d38.png

Click on the package name of the application to see the frame rate histograms and other settings:

3b760aa953f92a70.png

This confirms the proper working of the Android Performance Tuner integration.

9. Build the game and upload it to the Play Store (optional)

The game has Android Performance Tuner properly integrated. You can now create a new build and upload it on the Play Console. You can then distribute it to testers to start collecting performance data.

Set a unique package name for the game

Every Android app has a unique application ID that looks like a Java package name, such as com.example.myapp. This ID uniquely identifies your app on the device and in the Google Play Store. If you already have a game released or uploaded to the Play Console, you already chose a package name for it.

In this Codelab, we're using the Boat Attack demo game. To be able to upload it on your account, you need to choose a new, unique application id.

Open the Player Settings (from the Build Settings window). In the Android tab, open Other Settings section and find the Package Name field:

b2fbdfb3da24e216.png

Enter a unique, valid application id.

Create and setup a keystore for the game

Android requires that all apps are digitally signed with a certificate before they are installed on a device or updated.

We'll create a Keystore for the game in this codelab. If you're publishing an update to an existing game, reuse the same Keystore as you did for releasing previous versions of the app.

Create a keystore

You can create a Keystore with Android Studio or generate one on the command line. Using the command line, navigate to a folder where you want to store the key, then run keytool:

keytool -genkey -v -keystore mykeystore.keystore -alias alias -keyalg RSA -keysize 2048 -validity 10000

Answer the questions about your identity and confirm by entering yes when asked if the details are correct. You'll need to enter a password and an alias password.

Set up the keystore in Unity

Now that you have a keystore, navigate to Player Settings (from the Build Settings window). In the Android tab, open the Publishing Settings section. Check Custom Keystore, and then select your keystore file. Enter the password that was used for the keystore, the alias name and the alias password. These are the ones you chose when creating the keystore using Android Studio or the keytool command line tool. Note that the keytool command uses the same password for the keystore and alias, which is acceptable for this codelab but discouraged for production apps.

6fe0ff80fb8d6bfe.png

Privacy

Please review your app's Privacy Policy to ensure that it appropriately reflects that data about devices and usage may be shared with Google. Under Section 3.b the Google APIs Terms of Service, which governs your use of the Android Performance Tuner APIs, you must:

"comply with all applicable privacy laws and regulations including those applying to PII. You will provide and adhere to a privacy policy for your API Client that clearly and accurately describes to users of your API Client what user information you collect and how you use and share such information (including for advertising) with Google and third parties."

Modify the game to keep the bundle size under Play Store's limit of 200MB

Remove the demo scene from the build

Remove the demo_Island scene from the build. If you've not done it previously, go back to the Build Settings window, clear the checkbox for the demo_island scene, and make sure both main_menu and level_island are checked. Also ensure main_menu has a value of 0. If it has not, drag and drop it at the top of the list.

f9182897009ffd37.png

Reduce the data used by textures

In Build Settings, set Texture Compression to ASTC.

b2b5aaa8fe1fea92.png

Override the texture settings for the AlbedoAO, MSLL and Normal files for both the Interceptor and Renegade boats to make them Max Size of 512.

e962c21e215e4c76.png

Build the game as an Android App Bundle

The game is almost ready. Instead of building and submitting to the Play Store an APK file, we'll build an Android App Bundle. When you upload an Android App Bundle, Google play is able to automatically build and serve APKs that are optimized for each device configuration. This means that your users have a smaller game to download and install on their phone.

Games uploaded as Android App Bundles also benefit from a size limit of 200 MB. It's higher than the default limit of 100 MB for a single traditional APK. This will be useful for this codelab as the game, even with just the demo scene, is larger than 100 MB.

In the Build Settings window, check Build App Bundle (Google Play).

b8992811a96f3ca9.png

That's all that is needed to generate an Android App Bundle (an .aab file).

Build the game

The game should be ready! In the Build Settings window, ensure Development Build is not checked, and click on Build. Choose a location for the Android App Bundle file.

Check that you've covered everything

Before uploading your Android App Bundle (.aab file) to the Play Console, please check that you have:

  • Enabled Optimized Android Frame Pacing
  • Recorded loading times (highly recommended)
  • Validated the integration using logcat
  • If you're publishing a game to your user or testers: reviewed and updated your privacy policy as needed
  • Confirmed that you or other relevant game engineers have access to Android vitals in the Play Console

If you decide to use custom fidelity parameters or custom annotations (in addition to the level name and loading state), ensure you have added them in the plugin settings and integrate them in your game, using AndroidPerformanceTuner, as you did for the loading annotation.

Upload the game and create a release on an internal testing track

Use the Google Play Console to create an app, fill information about it and create a new internal testing release. Upload your Android App Bundle for this internal testing release. This will allow you to test your app and see the results in the Play Console.

Note that it's important to use an internal testing release to test your integration of the Android Performance Tuner. You can publish to other tracks (closed testing, open testing or production), but you'll need a large number of users to play your game before seeing the data in the Play Console.

10. Visualize results and insights in the Google Play Console (optional)

Open the Android Vitals page

Open the Google Play Console and choose the app you've uploaded. In the menu, choose Android Vitals > Performance > Frame Rate in the Quality section:

97d8258ca22a94a.png

If you open the page just after submitting your app for testing, it will probably be empty as no data was received and aggregated yet:

cb03a440ecbf9ccf.png

Ensure your game is played for the data to flow in. As it's a demo, you can let it run on a few devices.

You can already set the target frame rate for your game - allowing insights to be adapted to your game expected performance. In our example, we'll set it to 30fps. This is the default, so we can simply click Dismiss.

Exploring the results from the Android Vitals page

After your game is played by a certain number of users, you'll be able to see the charts showing how the game is performing.

Ensure you're looking at the data from the proper version of your app by selecting it at the top of the page:

210fea23c940f105.png

The Summary section shows how many sessions have been recorded, and the number of frames considered slow for these sessions:

415a8592b6027857.png

The Insights section shows more details, with slow frames per device model in Device model issues section and per annotation in the Annotation issues section:

b6bb81a2043fb90d.png

The next section allows you to explore the data in a chart:

63ae373acebd2cda.png

The 90th percentile of frame time for each device model is represented there, ordered by Quality level. In this codelab, we'll have only one quality level, which is automatically mapped by Android Performance Tuner from the Unity quality levels.

For more information on how to understand your performance metrics and insights, see Understand Android Performance Tuner insights.

11. Congratulations

Congratulations, you have successfully added Android Performance Tuner to a game, verified the integration and checked the results on the Google Play Console.

As you roll out your game to players, keep an eye on the insights to identify devices with issues or scope out potential improvements to add to your game.

What's next?