After creating an updated version of my latest Ludum Dare game, I decided to use it as an exercise in web publishing of games. To me, the interesting thing about publishing a game on a web portal – even one as simple and rough as one created in a little bit more than 48 hours – is that you can get a community of players to test, rate and give suggestions on your games, as well as get access to custom APIs for things like site-wide high-scores, achievements and statistics.

A website I decided to target for this experience was Kongregate, one of the biggest web game portals our there. A web gaming portal normally means “Flash games”, but like many others of its kind, Kongregate also accepts Unity games.

Kongregate also implements an interesting API that can be used by games when they’re published there. I believe the API is only officially supported for Flash and JavaScript, more or less, but Unity developers can still use it with the help of Unity’s external application interface (which allows for JavaScript calls from the Unity web plugin).

However, when reading on how to do this, I ran into two issues. First, most of the examples on how to use the statistics API from Unity are based on using JavaScript within your game (1, 2), while I was using C# instead; and second, and most importantly, all implementations depended on the oh-so-common pattern of creating an empty GameObject instance in a Unity scene and then attaching scripts to it (then getting a reference to it everywhere else via magic strings), rather than just a pure code-based solution. In fact, the API itself looks for a GameObject when returning the result of calls.

As much as I’ve been trying to give in to the proliferation of GameObjects everywhere that seem to be mandatory in Unity projects, to me the only solution was a clean C#-based implementation of the code – one that creates its own GameObject when necessary. The result is a single class that can be copied anywhere on your “Scripts” folder:

using System; using UnityEngine; public class KongregateAPI:MonoBehaviour { // Properties private bool _isConnected; private int _userId; private string _userName; private string _gameAuthToken; // ================================================================================================================ // MAIN EVENT INTERFACE ------------------------------------------------------------------------------------------- void Start() { _isConnected = false; _userId = 0; _userName = "Guest"; _gameAuthToken = ""; } void Awake() { // Instructs the game object to survive level changes DontDestroyOnLoad(this); // Begin the API loading process if available Application.ExternalEval( "if (typeof(kongregateUnitySupport) != 'undefined') {" + " kongregateUnitySupport.initAPI('" + gameObject.name + "', 'OnKongregateAPILoaded');" + "}" ); } // ================================================================================================================ // PUBLIC INTERFACE ----------------------------------------------------------------------------------------------- public static KongregateAPI Create() { // Create a game object with a reference to the API GameObject newGameObject = new GameObject("KongregateAPIObject-" + (Time.realtimeSinceStartup)); KongregateAPI instance = newGameObject.AddComponent<KongregateAPI>(); return instance; } public void OnKongregateAPILoaded(string __userInfoString) { // Is connected _isConnected = true; // Splits the user info parameter string[] userParams = __userInfoString.Split('|'); _userId = int.Parse(userParams[0]); _userName = userParams[1]; _gameAuthToken = userParams[2]; } public void SubmitStats(string __name, int __value) { Application.ExternalCall("kongregate.stats.submit", __name, __value); } public bool isConnected { get { return _isConnected; } } public int userId { get { return _userId; } } public string userName { get { return _userName; } } public string gameAuthToken { get { return _gameAuthToken; } } }

And it works like this:

// Create an instance of the API during setup in your game Main class KongregateAPI kongregate = KongregateAPI.Create(); // Later, submit stats using it kongregate.SubmitStats("high-score", 1000); kongregate.SubmitStats("tanks-destroyed", 1);

I have also added this class and some instructions to a GitHub repository, just in case.

With this implementation, I was able to easily add statistics to the Kongregate version of the game, creating a “high score” table of sorts countint the number of moves performed by players prior to completing each level. I don’t really anticipate any high competition for this. As an exercise in C# and Unity development, however, it was surprisingly pleasant and straightforward to get results.