Game Overrides integration with CCD

Game Overrides allow you to target content to specific audiences, for example, by running A/B tests, and customizing content to geographical location and specific periods of time. Badges identify the intended content, and Remote Config tests that content without affecting live players, while also distributing badged content to specific players.

To integrate Game Overrides, complete the following steps:

  1. Install the Remote Config package
  2. Link your Project ID
  3. Create an Override to target content by using your CCD badges
  4. Integrate Remote Config into your game code
  5. Retrieve the appropriate assets from CCD

Install the Remote Config package

For information about installing packages, see Package Manager.

These steps may vary depending on which version of the Unity Editor you’re using.

  1. In the Unity Editor, select WindowPackage Manager.
  2. In the Packages List View, select Remote Config.
  3. In the Package Specific Detail View, select and install the version you need to import Remote Config into your project.

If you haven’t done so already, you must link your Unity project to a Project ID.

To link your project from the Unity Editor:

  1. Open the Services window (Window > General > Services).
  2. Select General settings.
  3. In the Services section of the Project settings menu, select your Organization from the dropdown. You must be signed in to Unity Hub to view a list of associated Organizations.
  4. Select Use an existing Unity project ID to link a project to an ID that you previously created on the developer dashboard, or Create project ID to link your project to a new ID.

Create an Override

You can create an Override on the Unity Cloud Dashboard either from the Game Overrides service or from the Cloud Content Delivery service. See Create an Override.

  1. Go to the Game Overrides service by selecting LiveOps in the navigation bar, and then in the secondary navigation bar, select Game Overrides > Overrides.
    You can alternatively navigate to the Overview page by selecting Create Override in the Targeting tab of your bucket in the Cloud Content Delivery service itself.

  2. Select Create Override.

  3. Give your Override a name and select Next.

  4. Choose which players to target by specifying a JEXL condition, and then specify what percentage of these players to target. Select Next.

  5. Select + Choose content type, and then select Cloud Content Delivery > Badge. Select Done.

    To create an Override by using a regular Remote Config configuration instead of targeting a CCD badge, select Config Overrides. See Remote Config.

  6. Select Choose a bucket, and then pick the bucket you want to use.

  7. Select Choose your badge, and then pick the badge you want to use. Select Choose, then select Next.

  8. Choose the Start and End Date to run your Override. Select Finish.

  9. Select Enable to activate your Override.

Integrate Remote Config into your game code

The RemoteConfig API is included in the Unity.Services namespace, which you must include in your game script. For more information on its classes and methods, see the Remote Config Scripting API documentation.

The Remote Config service has an accessible RemoteConfigService instance to handle fetching and applying your configuration at runtime. In this example, you use it to fetch the key-value pair for your CCD configuration defined by your Override. The key for this pair is the static string CCD_CONFIG_KEY. You then invoke your ApplyCcdConfig function when the retrieval succeeds. ApplyCcdConfig takes a ConfigResponse struct, which represents the response to a fetch request.

C#

public struct userAttributes {}
public struct appAttributes {}
 
async Task InitializeRemoteConfigAsync()
{
  // initialize handlers for unity game services
  await UnityServices.InitializeAsync();
 
  // remote config requires authentication for managing environment information
  if (!AuthenticationService.Instance.IsSignedIn)
  {
    await AuthenticationService.Instance.SignInAnonymouslyAsync();
  }
}
 
async void Start()
{
    if (Utilities.CheckForInternetConnection())
    {
        await InitializeRemoteConfigAsync();
    }
 
    RemoteConfigService.Instance.appConfig = RemoteConfigService.Instance.GetConfig("ccd");
    RemoteConfigService.Instance.FetchCompleted += ApplyCcdConfig;
    RemoteConfigService.Instance.FetchConfigs("ccd", new userAttributes(), new appAttributes());
}
 
void ApplyCcdConfig(ConfigResponse configResponse)
{
    switch (configResponse.requestOrigin)
    {
        case ConfigOrigin.Default:
            Debug.Log("Default values will be returned");
            break;
        case ConfigOrigin.Cached:
            Debug.Log("Cached values loaded");
            break;
        case ConfigOrigin.Remote:
            Debug.Log("Remote Values changed");
 
            if (RemoteConfigService.Instance.appConfig.HasKey("CCD_CONFIG_KEY"))
            {
                // get the correct key-value pair for CCD (the key will always be "CCD_CONFIG_KEY")
                string jsonValue = RemoteConfigService.Instance.appConfig.GetJson("CCD_CONFIG_KEY");
                // you will use jsonValue in the next step
            }
 
            break;
    }
}

Retrieve the appropriate assets from CCD

After you have successfully fetched the CCD configuration, you can then extract your bucket information and badge name to retrieve the appropriate assets from CCD.

Start by defining a CcdConfig class.

C#

public class CcdConfig
{
   public string bucketId;
   public string bucketName;
   public string badgeName;
}

In your ApplyCcdConfig function, you can then extract these values from the fetched CCD configuration and use them to retrieve the appropriate assets from CCD.

C#

// extract the config values that you have defined when creating your Override
CcdConfig ccdConfig = JsonUtility.FromJson<CcdConfig>(jsonValue);
 
// the bucketId and badgeName are required to fetch the appropriate assets
var bucketId = ccdConfig.bucketId;
var badgeName = ccdConfig.badgeName;
 
// fetch the entry from CCD
// Note that for a dynamic file path, a config override can be used in order to fetch
// the correct file path for your asset
JObject entry = CcdManager.Instance.GetEntry(bucketId, badgeName, "ENTRY_PATH");
// fetch the entry's content from CCD
var content = CcdManager.Instance.GetContent(bucketId, entry["entryid"].ToString());
 
// use your asset(s) as needed
// YOUR CODE HERE

The CCDManager class uses CCD’s client API to fetch the asset. You must attach the CCDManager to a game object in each scene.

If your assets are large, consider fetching them asynchronously.

Your CCDManager class might look something like the following code sample:

C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
using Unity.RemoteConfig;
 
using System.Net;
using System;
using System.IO;
 
public class CcdManager : MonoBehaviour
{
 
   private static string projectId = "YOUR_PROJECT_ID_HERE";
   private static string ccdBaseUrl = $"https://{projectId}.client-api.unity3dusercontent.com/client_api/v1/";
 
   private static CcdManager m_Instance;
   public static CcdManager Instance { get { return m_Instance; } }
 
   private void Awake()
   {
     if (m_Instance != null && m_Instance != this)
       {
           Destroy(this.gameObject);
           return;
       }
 
       m_Instance = this;
       DontDestroyOnLoad(this.gameObject);
   }
 
   public JObject GetEntry(string bucketId, string badgename, string entrypath) {
     var entryUrl = $"{ccdBaseUrl}/buckets/{bucketId}/release_by_badge/{badgename}/entry_by_path/?path={entrypath}";
 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(entryUrl);
     HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 
     StreamReader reader = new StreamReader(response.GetResponseStream());
     string jsonResponse = reader.ReadToEnd();
     JObject ccdEntry =  JObject.Parse(jsonResponse);
 
     return ccdEntry;
   }
 
   public string GetContent(string bucketId, string entryid) {
     var contentUrl = $"{ccdBaseUrl}/buckets/{bucketId}/entries/{entryid}/content/";
 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format(contentUrl));
     HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 
     StreamReader reader = new StreamReader(response.GetResponseStream());
     string contentValue = reader.ReadToEnd();
 
     return contentValue;
   }
}

You have now successfully retrieved the assets defined by your Override.