Getting Started
The Unity integration example is based on the Photon Angry Bots demo game by Unity Technologies and Photon. To get started, you will need a working Unity development environment and the Unity project from our GIT repository.
Note:
Please make sure when implementing Unity that SSL support is added for the Ninja Metrics certs.
JSON Content Type - When sending JSON data to the Ninja Metrics API it is required to properly set the "Content Type" header to "application/json". A lot of packages do this automatically, but if you receive a 415 error then that is likely the cause.
Now you're ready to begin adding scenes to your build settings.
Next, compile the project in MonoDevelop. If you're using Windows and installed Unity to a non-default location, you will first need to update the various .csproj and .unityproj files to point to your Unity install directory. You will have to replace all occurrences of C:\Program Files (x86)\Unity with the correct path, as well as all occurrences of C:/Program Files (x86)/Unity with the correct path using forward slashes.
The project can now be run from within the Unity environment.
Web Requests in Unity
To send requests to Ninja Metrics within a Unity game we are utilizing the WWW class provided by UnityEngine http://docs.unity3d.com/Documentation/ScriptReference/WWW.html. This provides a small utility module for making requests to a server asynchronously, without blocking the rest of the game. The process of initializing and sending a request begins as soon as the WWW object is instantiated. For making the HTTPS POST requests required by the JSON API, the WWW constructor takes a String for the url, byte[ ] for the POST data which will contain the JSON payload, and a Hashtable for request headers. Since the requests are made asynchronously, if the developer wishes to examine the response, the proper design pattern in Unity is to wait for the response inside a coroutine. A coroutine will execute in parallel and can be paused at any point using a yield statement. The coroutine will resume and then inspect the response by using the WWW request object as the yield return value. Note it is not necessary to implement a coroutine to make a successful request from Unity in the standard use case. It is only needed if the developer wishes to inspect the response for debugging or error handling purposes.
This example implements three different events: the Create Account event, the Login event, and the Logout event.
Create Account Event (#9) from MainMenu.cs line 43:
// Build the Ninja Metrics API Endpoint with the following parameters: // client_id: the id of the client on the dashboard // app_id: the id for this game/app on the dashboard // app_pwd: the password or access token for this app on the dashboard // api_client: JSON since this is a direct request to the Ninja JSON API string ninjaApiEndpoint = "https://api.ninjametrics.com/event?client_id=1086&app_id=5056&app_pwd=baa50601ad3bc3a2c2177d83b75fd826&api_client=JSON"; // Build json payload. JSONClass payload = new JSONClass(); // UTC ISO-8601 timestamp. string timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); payload.Add("timestamp", new JSONData(timestamp)); JSONClass data = new JSONClass(); data.Add("type", new JSONData(9)); // Create Account event type data.Add("account_id", new JSONData("ninja@example.com")); data.Add("account_sub_type", new JSONData("Free")); data.Add("account_lang", new JSONData("en-US")); data.Add("account_country", new JSONData("US")); data.Add("account_gender", new JSONData("N")); data.Add("account_dob", new JSONData(new DateTime(1985, 7, 12).ToString("o"))); // "o" is a UTC ISO-8601 format data.Add("account_currency_balance", new JSONData(0)); data.Add("platform", new JSONData("Unity-" + Application.platform)); // Deployed platform payload.Add("data", data); // Convert json to byte data for WWW object POST data. byte[] postData = Encoding.ASCII.GetBytes(payload.ToString().ToCharArray()); // Build request headers. Hashtable headers = new Hashtable(); headers.Add ("Content-Type", "application/json"); // Create a WWW object that will send a request and receive its response. WWW request = new WWW(ninjaApiEndpoint, postData, headers); // Start a coroutine to wait for the response in parallel. // This is only required if you wish to inspect the response // for error handling or debugging purposes. StartCoroutine(WaitForRequest(request));
Login Event (#1) from MainMenu.cs line 133:
// Build the Ninja Metrics API Endpoint with the following parameters: // client_id: the id of the client on the dashboard // app_id: the id for this game/app on the dashboard // app_pwd: the password or access token for this app on the dashboard // api_client: JSON since this is a direct request to the Ninja JSON API string ninjaApiEndpoint = "https://api.ninjametrics.com/event?client_id=1086&app_id=5056&app_pwd=baa50601ad3bc3a2c2177d83b75fd826&api_client=JSON"; // Build json payload. JSONClass payload = new JSONClass(); // UTC ISO-8601 timestamp. string timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); payload.Add("timestamp", new JSONData(timestamp)); JSONClass data = new JSONClass(); data.Add("type", new JSONData(1)); // Login event type data.Add("account_id", new JSONData("ninja@example.com")); data.Add("character_id", new JSONData("ninja")); data.Add("shard_id", new JSONData(0)); data.Add("platform", new JSONData("Unity-" + Application.platform)); // Deployed platform data.Add("area_id", new JSONData(0)); payload.Add("data", data); // Convert json to byte data for WWW object POST data. byte[] postData = Encoding.ASCII.GetBytes(payload.ToString().ToCharArray()); // Build request headers. Hashtable headers = new Hashtable(); headers.Add ("Content-Type", "application/json"); // Create a WWW object that will send a request and receive its response. WWW request = new WWW(ninjaApiEndpoint, postData, headers); // Start a coroutine to wait for the response in parallel. For this // implementation, this is required because a call to // Application.LoadLevel was made directly below and the request object // could be destroyed before it's completed. To guarantee the request is // made we moved the loading of the level to this coroutine. StartCoroutine(WaitForRequestAndLoadNextLevel(request)); // Moved to inside the above coroutine to ensure the request is sent. //Application.LoadLevel(Application.loadedLevel + 1);
Logout Event (#2) from GameManager.cs line 119
// Send successful Logout event to Ninja Metrics. // For the purpose of this demo we consider leaving a room a Logout event. // Build the Ninja Metrics API Endpoint with the following parameters: // client_id: the id of the client on the dashboard // app_id: the id for this game/app on the dashboard // app_pwd: the password or access token for this app on the dashboard // api_client: JSON since this is a direct request to the Ninja JSON API string ninjaApiEndpoint = "https://api.ninjametrics.com/event?client_id=1086&app_id=5056&app_pwd=baa50601ad3bc3a2c2177d83b75fd826&api_client=JSON"; // Build json payload. JSONClass payload = new JSONClass(); // UTC ISO-8601 timestamp. string timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); payload.Add("timestamp", new JSONData(timestamp)); JSONClass data = new JSONClass(); data.Add("type", new JSONData(2)); // Logout event type data.Add("account_id", new JSONData("ninja@example.com")); data.Add("character_id", new JSONData("ninja")); data.Add("shard_id", new JSONData(0)); data.Add("platform", new JSONData("Unity-" + Application.platform)); // Deployed platform data.Add("area_id", new JSONData(0)); payload.Add("data", data); // Convert json to byte data for WWW object POST data. byte[] postData = Encoding.ASCII.GetBytes(payload.ToString().ToCharArray()); // Build request headers. Hashtable headers = new Hashtable(); headers.Add ("Content-Type", "application/json"); // Create a WWW object that will send a request and receive its response. WWW request = new WWW(ninjaApiEndpoint, postData, headers); // Start a coroutine to wait for the response in parallel. For this // implementation, this is required because a call to // Application.LoadLevel was made directly below and the request object // could be destroyed before it's completed. To guarantee the request is // made we moved the loading of the level to this coroutine. StartCoroutine(WaitForRequestAndLoadNextLevel(request)); // Moved to inside the above coroutine to ensure the request is sent. //Application.LoadLevel(Application.loadedLevel + 1);
Common coroutine functions used by events:
/** * A Coroutine that waits for the request to return a response, so it can be * inspected. * * @param a WWW object to inspect **/ IEnumerator WaitForRequest(WWW request) { // Wait for the response from Ninja Metrics. yield return request; // Inspect the response. if (request.error != null) { // An error occurred. Debug.Log("Error: " + request.error); } else { // Response was received. Debug.Log("Response: " + request.text); } }
Debugging the Unity Application
If you wish to step through the various calls, within MonoDevelop choose Run→Attach to Process. Select the Unity Editor process and click Attach. After setting desired breakpoints, run the game from within the Unity environment. When a breakpoint is hit, the MonoDevelop taskbar item will flash, and you may switch to that window and start debugging.