Remote Display Plugin for Unity Game Engine

The Google Cast Remote Display plugin for Unity allows developers to easily add support for the Remote Display API to their Unity applications. The plugin's scripts and prefabs make it easy to develop a new game or adapt an existing Unity game to support Cast.

Setting Up

  • Download version 5.1 of Unity. Note: Unity 5.1 or 5.0 is required. Unity 5.2 and above is not supported due to a Unity audio bug.
  • Download mobile SDKs:
    • Android: To get the development environment, download Android Studio (which includes the SDK).

      Alternatively, if you prefer the minimum required to run Unity on Android, download only the Android SDK.

      Your copy of the SDK needs to include the latest Google Play services SDK (found in the "Extras" section in the SDK Manager).

      In either case, note where the SDK is installed, as you will need that path in a later step.

    • iOS: Download Xcode.

Download and Import the Plugin

The Google Cast Remote Display plugin for Unity can be downloaded in two ways:

  • GitHub: Download the package file. Import the Remote Display plugin to your game project:
    1. In Unity select the Assets > Import Package > Custom Package menu options.
    2. Select the GoogleCastRemoteDisplay.unitypackage file you downloaded and click Open.
    3. Make sure all the boxes are checked in the Importing Package dialog and click Import.
      Note: You may be warned that the APIs will be automatically upgraded. If that happens, accept it and continue.
  • Unity Asset Store: Within Unity use the Window / Asset Store menu options to display the Asset Store window. Search for "Google Cast Remote Display" and download the plugin.

Google Cast Registration

Before developing a Remote Display application, you will need to register your app with the Google Cast SDK Developer Console. See Registration for more information. When you add your application in the console, select "Remote Display Receiver" for the receiver type. You will be provided with an app ID which you will need to configure with the Remote Display plugin within Unity as described below.

Mobile Platforms

Once the game is developed in Unity, it can then be built for various platforms. The Google Cast Remote Display API is supported on:

  • Android 4.4 KitKat (API level 19) or later
  • iOS version 8 or later
Chrome is not supported.

Android

Build Settings

The Android SDK has to be configured with Unity. In Unity, click Preferences > External Tools > Android SDK Location, then select the folder where you downloaded and unzipped the Android SDK.

Configure Unity to build an Android application:

  1. Click File > Build Settings… to open the Build Settings window.
    1. Select Android in the platform list, if it isn't selected already.
    2. Click Switch Platform to make Android your default build target.
  2. Click on Player Settings…
    1. Expand the Other Settings section by clicking on it.
    2. Enter the Bundle Identifier. The bundle identifier should be unique and typically of this form: com.yourcompany.appname.
    3. Change the Minimum API Level value to Android 4.4.

Android Libraries

Copy the following additional libraries into the Unity project to make the Remote Display API work for Android. The Android portion of the plugin depends on these libraries:

  • Media Router
  • Google Play Services
  • App Compat

Make of a copy of these Android SDK directories into the Assets/Plugins/Android folder:

  • extras/google/google_play_services/libproject/google-play-services_lib
  • extras/android/support/v7/appcompat
  • extras/android/support/v7/mediarouter

You should now have the following in the Assets/Plugins/Android folder:

  • google-cast-remote-display_unity3d_lib.aar
  • google-play-services_lib
  • appcompat
  • mediarouter

Android Manifest

If you don't have a top level Android manifest for your Unity project, you can use the following AndroidManifest.xml template. Change the package name to match the Bundle Identifier you configured in the Unity build settings for Android.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="PUT_YOUR_BUNDLE_ID_HERE" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal">
  <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
  <application android:theme="@android:style/Theme.NoTitleBar" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false" android:isGame="true" android:banner="@drawable/app_banner">
    <activity android:label="@string/app_name" android:screenOrientation="landscape" android:launchMode="singleTask"
	android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale"
	android:name="com.google.cast.unityplugin.UnityPlayerActivity">
      <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="google.cast.unityplugin.UnityPlayerActivity" android:value="true" />
    </activity>
  </application>
  <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="22" />
  <uses-feature android:glEsVersion="0x00020000" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WAKE_LOCK" />
  <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
</manifest>

Place the AndroidManifest.xml file in the Unity project Assets/Plugins/Android folder.

Building and Running the Project

In Unity select the File > Build & Run menu option. You will be prompted for a name for the APK file and then Unity will upload the APK to your mobile device.

iOS

You will need to use your Apple developer account and Xcode to build the Unity game and run it on an iOS device.

Build Settings

Configure Unity to build an iOS application:

  1. Click File > Build Settings… to open the Build Settings window.
  2. Select iOS in the platform list, if it isn't selected already.
  3. Click the Switch Platform to make Android your default build target.
  4. Click on Player Settings…
  5. Expand the Other Settings section by clicking on it.
  6. Enter the Bundle Identifier. The bundle identifier should be unique and typically of this form: com.yourcompany.appname.
  7. Change the Target iOS Version value to 8.0.

Building the Project

  1. Open up the build settings by going to File > Build Settings.
  2. Click Build. This prompts you for a save name, and prepares an Xcode project in the directory your Unity project/your save name. In the next section we will deploy that to your iPhone.

Deploying the Project in Xcode

  1. Open Xcode. From the File > Open... menu, open the Xcode project that you created. It will be a file called Unity-iPhone.xcodeproj inside the directory you just saved under in the last section.
  2. Select the Unity-iPhone project by clicking on it.
  3. Now run the project, either by clicking the play button, or by going to Product > Run.

If all went well, you should see "Build Succeeded" and the game launches on your iOS device.

Unity Prefabs

To help Unity developers use the Remote Display API and support the Cast UX guidelines, we have created the following two Unity prefabs, CastRemoteDisplayManager and CastDefaultUI, that you can use in your game. We also have created a third prefab, the CastRemoteDisplaySimulator, which is described later in the Debugging section.

CastRemoteDisplayManager

The CastRemoteDisplayManager class is instantiated as a singleton and is the entry point in Unity for interacting with the Android and iOS native implementations of Google Cast Remote Display. CastRemoteDisplayManager also provides a scripting API which is discussed in a later section.

Add the CastRemoteDisplayManager prefab from the Assets/Plugins/GoogleCastRemoteDisplay project folder to your scene hierarchy. The CastRemoteDisplayManager must be at the top level of your scene hierarchy.

Select the CastRemoteDisplayManager in your hierarchy, and for the Cast App Id, enter the Application Id you obtained from the Google Cast Developer Console.

By default, the main camera has an audio listener enabled. You can use this audio listener to send audio to the TV when the game is casting.

Typically you can set main camera as the value for both the RemoteDisplayCamera and RemoteAudioListener values of the CastRemoteDisplayManager in the scene.

CastDefaultUI

The CastDefaultUI prefab provides several UI's that you can use to comply with the Google Cast Design Checklist:

  • Cast button including support for connecting animation state.
  • First-time Cast dialog to introduce the cast feature to users.
  • Cast list dialog to display the list of discovered devices.
  • A dialog to allow the user to disconnect from the Cast device.
  • Dialog to display various errors.

These features are detailed in the CastDefaultUI class.

To add a simple pre-built UI to select a cast device, follow these steps:

  1. Add the CastDefaultUI prefab from Assets/Plugins/GoogleCastRemoteDisplay to your scene hierarchy. This must be at the top level of your scene hierarchy.
  2. Set the Canvas / Sort Order of the CastDefaultUI so that the Cast button gets events over any parts of the UI below it in the scene layers.

To change the UI for the Cast dialog list, which displays the list of devices:

  1. Add the CastListElement prefab from Assets/Plugins/GoogleCastRemoteDisplay/UI to your scene hierarchy.
  2. In the inspector, change your CastListElement values.
  3. Drag the customized CastListElement into the project window, and rename it CustomCastListElement.
  4. In the project hierarchy, select CastDefaultUI/CastListDialog.
  5. In the inspector, change the Cast List Dialog/List Element Prefab to your CustomCastListElement.

Remote Display Unity Plugin API

The CastRemoteDisplayManager instance provides various methods that can be used to script the behavior of the remote display at runtime from within the Unity game.

Here are some of the important functions, properties and events:

Entry point
GetInstance: Returns the instance of the class, or null if no object has been created.
Configuration
RemoteDisplayCamera: (property) The Camera that should be displayed in the remote display. Can be set at runtime. Ignored if RemoteDisplayTexture is set.
RemoteDisplayTexture: (property) The texture that should be displayed in the remote display. Can be set at runtime.
RemoteDisplayPausedTexture: (property) The texture that should be displayed in the remote display if the game gets backgrounded on the phone or tablet. Can be set at runtime.
Lifecycle
SelectCastDevice: (function) This should only be called after the CastDevicesUpdated event is fired. Use the deviceId field of the CastDevice struct from GetCastDevices.
StopRemoteDisplaySession: (function) Stops casting.
Queries
GetCastDevices: (function) This returns a list of CastDevice structs, which includes the following:
  • deviceId: Use this to select cast devices using the scripting API.
  • deviceName: The name of the cast device to show in your GUI.
  • status: The current status text of the cast device to show in your GUI.
GetSelectedCastDevice: (function) Returns the device we are currently casting to, or null if no cast session is currently active.
IsCasting : (function) Whether there is an active cast session. This will be set to true from the moment the RemoteDisplaySessionStartEvent fires and until the session ends.
GetLastError: (function) Returns the last error encountered by the plugin, or null if no error has occurred.
Events
CastDevicesUpdatedEvent: (event) Is fired when the list of available cast devices has been updated.
RemoteDisplaySessionStartEvent: (event) Is fired when a cast session starts.
RemoteDisplaySessionEndEvent: (event) Is fired when a cast session ends.
RemoteDisplayErrorEvent: (event) Is fired when an error is encountered.
Note: All event listeners must take a parameter of type CastRemoteDisplayManager and return void.

Here is a snippet of code on how these methods could be used in a C# script:

public GameObject pauseButton;
public GameObject pausePanel;
private GameObject castUIController;

void Start () {
  displayManager = CastRemoteDisplayManager.GetInstance();
  displayManager.RemoteDisplaySessionStartEvent
     .AddListener(OnRemoteDisplaySessionStart);
  displayManager.RemoteDisplaySessionEndEvent
      .AddListener(OnRemoteDisplaySessionEnd);
  displayManager.RemoteDisplayErrorEvent
    .AddListener(OnRemoteDisplayError);
  castUIController = GameObject.Find("CastDefaultUI");
  pausePanel.SetActive(false);
  pauseButton.SetActive(false);
}

public void OnRemoteDisplaySessionStart(CastRemoteDisplayManager manager) {
  castUIController.SetActive(false);
  pauseButton.SetActive(true);
}

public void OnRemoteDisplaySessionEnd(CastRemoteDisplayManager manager) {
  castUIController.SetActive(true);
  pauseButton.SetActive(false);
}

public void OnRemoteDisplayError(CastRemoteDisplayManager manager) {
  castUIController.SetActive(true);
  pauseButton.SetActive(false);
}

All RemoteDisplay prefabs are singletons — that is, there is only one object of each type. CastRemoteDisplayManager, CastRemoteDisplaySimulator, and CastDefaultUI will persist themselves across multiple scenes. The gameObjects will persist across scenes, but their configuration may need to be updated, depending on game logic (most notably the camera).

Designing for Multiple Screens

Before you implement the UX for your game you need to consider how Cast will be integrated within your game:

  • Cast-required: a game that can be played only on a big screen as part of the Google Cast experience.
  • Cast-enabled: a game that can also be played on the device itself, away from a big screen.

This distinction will determine how you allow the user to select a Cast device in the game UI. For Cast-required games, the user has to select the Cast device before the game can be played. For Cast-enabled games, the user can play the game on the mobile device and at any time can decide to cast the game to the TV by clicking on the Cast button. Also, at any time the user can then click on the Cast button to disconnect from the Cast device and then play the game on the mobile device again.

You also need to consider how the user will control the game. You can use the mobile device sensors to create abstract controls which interacts with action on the screen via motion or touch. You can also create virtual controls where the player touches something on the device to control something else on the screen.

For visual design it is important not to fatigue the player by making them constantly look up and down. The television's experience should be designed to be viewed from across the room. This means big, readable text and nothing that looks "tappable". You need to decide what information is displayed on the TV and what is displayed on the mobile screen during the various stages of your game. While the user is casting, HUD information such as health indicators and scores should be displayed on the TV rather than the mobile device.

See our UX guidelines for more details and screenshots for the recommended Cast experience for games.

Implementing the UX

The Google Cast Remote Display plugin for Unity provides various ways for you to design the Cast UX for your game. These can be set as properties of the prefabs or can be set programmatically using the Remote Display Unity Plugin API.

Remote Screen

To render the TV display:

  • You can use an additional camera to render the remote display (see RemoteDisplayCamera value of CastRemoteDisplayManager).
  • Or you can use a texture for rendering the remote display (see RemoteDisplayTexture value of CastRemoteDisplayManager).

You can set the RemoteDisplayPausedTexture value of CastRemoteDisplayManager to automatically display a pause screen when the game is paused or your mobile app is backgrounded.

Controls

Unity provides support for mobile device input. The Unity standard assets implement various kinds of controllers that you can use for your game. Our sample game shows how to create virtual joysticks that can be used to control the game on the mobile device or on the remote display.

You should also consider using the mobile device accelerometer as an alternative way to control the gameplay.

Mobile Screens

Unity provides support for handling different mobile screen resolutions. In our sample game we use a Canvas Scaler component with the Ui Scale Mode set to Scale With Screen Size.

It is important to test your game on various mobile devices and screens sizes before you publish your game.

Debugging

It takes time to build the mobile version of the game every time you want to test changes to your game. To speed up development we have a Remote Display simulator you can use within the Unity editor to select Cast devices and view the remote display. This simulator will simulate the remote display by superimposing an image on the unity editor (while in play mode) that will show what would be sent to the TV while casting.

To add the simulator to the project, follow these steps in the Unity editor:

  1. Add the CastRemoteDisplaySimulator prefab from Assets/Plugins/GoogleCastRemoteDisplay to your scene hierarchy. This must be at the top level of your scene hierarchy.
  2. The Cast Devices section of the CastRemoteDisplaySimulator already has one virtual device by default. You can add additional devices (e.g. change Size to "2" and fill in dummy values for Device ID, Device Name, and Status).

The remoteDisplayErrorEvent is fired by the CastRemoteDisplayManager. You should use this to catch errors and elegantly handle the UX in your game. Typically you would use the returned error object information to present an error dialog to the user.

You can export the apps as mobile projects for Android Studio or Xcode. You can then use those development environments to study the logs generated by the apps when they run on the mobile devices.

Best Practices

Before you embark on adding support for Remote Display to your mobile game, you can simply mirror your existing game to a Cast device to gauge the experience (This is only an option for Android).

The Remote Display Unity Plugin supports the following features:

  • Display resolution: 720p/1080p
  • Display framerate: 30FPS/60FPS

These values can be configured in the CastRemoteDisplayManager prefab or using the CastRemoteDisplayConfiguration scripting API. To ensure consistently good remote display experiences for various mobile devices and networking conditions, we recommend using 720p/30FPS.

To reduce the CPU load on the mobile device, optimize any resources in you have in your game by reducing texture sizes. Games that are not optimized can lead to high CPU usage, high battery drain and increased mobile device temperatures. Aim to keep the CPU usage below 30%.

When the Unity mobile app is backgrounded, the plugin will automatically do various optimizations to reduce the battery usage. The game should not do any explicit optimizations for backgrounding like disabling Cast device discovery.

For any native code development these graphics options are supported:

  • OpenGL ES2/ES3 is supported on Android.
  • OpenGL ES2/ES3 and Metal are supported on iOS.

When developing a game, evaluate the following:

  • Image quality of a single rendered frame on the TV.
  • Smoothness or jerkiness of multiple frames presented on the TV.
  • Responsiveness of the game to user input.

Unlike a traditional mobile (or desktop or console) game, the previous items are affected by:

  • Available network bandwidth. (Is the user playing alone, or in a congested household?)
  • How often frames are sent from the device to the TV. (Is the game sending 15, 30, or 60 fps?)
  • How big are the frames sent from the device to the TV. (Is the game rendering 480, 720, or 1080p frames?)
  • The CPU/GPU of the mobile device. (Is the game running on a hand-me-down or a latest gen device?)
  • The video encoder of the mobile device. (This is not the same as the CPU or GPU - for example, some iPhones are better optimized thaniPads for Facetime video.)

Developers need to take into account these factors and adjust image quality and smoothness. It is also important to test the games on various mobile device encoders to see if the video encoder introduces any artifacts. For example, particle effects may not encode well regardless of how powerful the phone is.

Resources

We provide a number of resources for developers who use the Google Cast Remote Display plugin for Unity: