Working with Parse.com in Unity – Part 2 – Services, Helpers and Looming

Working with Parse.com in Unity – Part 2 – Services, Helpers and Looming

This is part of a three-post series on working with Parse.com in Unity. For more info please see the other posts in the series:

Part 1 – Intro and App Structure
Part 2 – Services, Helpers and Looming
Part 3 – Tests, Typescript and Common Code

In the last post I covered the basic app structure, in this post I want to cover some of the specifics of the front end, the Unity part.

Note all the code talked about can be found in the Parse Unity Sample Project on Github.

Services

I like to split my code up so that all the work that involves dealing with remote services are contained within “Service” classes. The service classes are responsible for taking game data and turning it into a form that the remote service can deal with, then translating the result and passing it back to the game.

In the sample project I have just one service, the UserService, which is responsible for logging a user in or signing them up or logging them out, basically all functionality that that concerns the “GameUser” class.

Tasks

Lets take a look at the Login method in the UserService class:

public Task<GameUser> Login(string email, string password)
{
	Debug.Log("Logging in..");

	return ParseUser.LogInAsync(email, password)
		.OnMainThread()
		.Then(t => Task.FromResult((GameUser)t.Result));
}

We can see that it takes in an email and password then logs in for us and returns a Task.

Parse uses Tasks throughout its Unity SDK as a way of handling asynchronicity. You will probably familiar with Tasks if you have done any work with aync / await in C# 5 or greater.

Unity runs on an old version of C# it doesn’t have any concept of Tasks baked in so Parse includes the System.Threading.Tasks namespace. Although Unity does not have any support for async / await you can still use the Tasks API in a Javascript-like Promise way.

Tasks allow us to provide a callback method that will be called when the Task returns, which allows the game to continue on running while we wait for the server to respond. For example, this is how we call Login:

private void Login()
{
	isLoading = true;
	userService.Login(usernameInp.text, passwordInp.text)
		.Then(OnLoggedIn, OnLoginError);                
}

private void OnLoginError(Exception e)
{
	isLoading = false;
	menus.ErrorPopup.Open("Error logging in!");
}

private void OnLoggedIn(GameUser user)
{
	isLoading = false;        
	menus.States.SetState("Logged In State");
}

The Then function after login is being called on the Task and is the first of my helper libraries that I have included in the sample project which imports my Unity Parse Helpers library.

In that library I have included a number of extension methods for Task that allow you to chain functions together for example from the SignupState:

private void Signup()
{
	isLoading = true;

	// Signup
	userService.Signup(usernameInp.text, passwordInp.text, playernameInp.text)

		// Then Login
		.Then(t => userService.Login(usernameInp.text, passwordInp.text))

		// Then we are done
		.Then(OnLoggedIn, OnError);                     
}

This makes chaining asynchronous logic together in Unity a breeze and you don’t ever have to deal with the headache of using yeild!

Threading

The first major headache I came across when using Parse in Unity is to do with threading. Note from my earlier example of Login in UserService:

public Task<GameUser> Login(string email, string password)
{
	Debug.Log("Logging in..");

	return ParseUser.LogInAsync(email, password)
		.OnMainThread()
		.Then(t => Task.FromResult((GameUser)t.Result));
}

The function “OnMainThread” is a helper extension I wrote to deal with the threading issue. If we were to remove that function then when we try to login Unity would throw an error something like:

2014-11-11_08-07-43

This is because below the covers Parse is making web calls on a separate thread and when it returns the result is passed back to us without returning to be main thread and pretty much everything in Unity needs to happen on the main thread so when we try to access a variable that lives on the main thread Unity crashes.

There are a few ways around this issue, Parse documents that you can use coroutines to deal with this, but I would really rather not have to use coroutines so instead I used another common solution, a “Loomer”.

A Loomer basically just takes a function and waits until the game is running on the main thread before executing the function. So behind the scenes my “OnMainThread” extension function is calling the loomer which ensures that any Tasks that follow it will execute on the main thread:

public static Task<T> OnMainThread<T>(this Task<T> task)
{ 
	var tcs = new TaskCompletionSource<T>();
	var loom = Loom.Instance;

	Action<Task<T>> a = t =>
	{
		loom.QueueOnMainThread(() =>
		{
			if (t.IsFaulted) tcs.SetException(t.Exception);
			else if (t.IsCanceled) tcs.SetCanceled();
			else { tcs.SetResult(t.Result); }
		});    
	};

	task.ContinueWith(a);
	return tcs.Task;
}

So whenever you call Parse functions in your services just make sure you call “OnMainThread()” and you should be good to go!

On a separate note, I have already previously mentioned that if you are going to write extension methods for Tasks you must make sure that you sepparate your action from the ContinueWith() else you will get an internal compiler error in Unity!

Errors

Unfortunately there is an issue in Unity with Parse that means that we cannot get proper error messages back from the server. For example if a user mistypes their email address when logging in all we get is a HTTP error code like “404 – Not found”, this is obviously not particularly helpful. Parse does actually return a better error than which can be seen if you use the Rest or .Net API but whatever reason in Unity that error message gets lost.

This is probably the single biggest drawback with using Parse.com with Unity but it is apparently a fundemental issue with Unity. I have started a thread on the Parse Google Group to see if we can get an update on this but im not holding any hope. I did hear a rumor that the new version of the Unity compiler (shipping in Unity 5+) will finally include improvements to network stack.

Generally you can work around it as you can guess what the issue is if an error occurs and handle it in your business logic. Its still really annoying however particularly when it comes to debugging and testing, hence why I have devoted another post to that very subject..

To Be Continued…

And thats basically it for dealing with Parse.com in Unity, I strongly reccomend checking out the source if you need more information on anything I have covered, hopefully it makes more sense.

In the next part ill talk about how to structure your backend so that you can easily test your cloud code.

Working with Parse.com in Unity 3D – Part 1 – Intro and App Structure

Working with Parse.com in Unity 3D – Part 1 – Intro and App Structure

This is part of a three-post series on working with Parse.com in Unity. For more info please see the other posts in the series:

Part 1 – Intro and App Structure
Part 2 – Services, Helpers and Looming
Part 3 – Tests, Typescript and Common Code

For a while it has been my intention to follow up my work with Parse.com in Unity, but other things have always gotten in the way and thus I have only just managed to get round to it.

Over the past 9 months of working with Parse I have encountered some pretty nasty issues which I decided to solidify by putting together this guide and sample project which I hope will help others out there!

But first..

What is Parse.com?

Parse.com is a backend as a service (BaaS). This means they take care of managing servers, operating systems, load balancing and all of that leaving you with a simple API that you can use to get what you need done.

I have been using Parse for most of my projects of late for a few reasons, mainly its ease of use (more of that later) and incredibly generous pricing:

2014-11-10_15-58-19
(thats about 77 million free API requests per month, per app!)

In comparison to the competition its much cheaper, Microsoft’s Azure based Mobile Services for example:

2014-11-10_16-00-33

Parse.com features a simple way to store..

var shield = new Armor
{
  DisplayName = "Wooden Shield",
  IsFireproof = false,
  Rupees = 50
};

shield.SaveAsync();

.. and retrieve data:

var query = new ParseQuery<Armor>()
    .WhereLessThanOrEqualTo("rupees", ((Player)ParseUser.CurrentUser).Rupees);
query.FindAsync().ContinueWith(t =>
{
    IEnumerable<Armor> result = t.Result;
});

You can also have routines run on the server written using Javascript:

Parse.Cloud.define("averageStars", function(request, response) {
  var query = new Parse.Query("Review");
  query.equalTo("movie", request.params.movie);
  query.find({
    success: function(results) {
      var sum = 0;
      for (var i = 0; i < results.length; ++i) {
        sum += results[i].get("stars");
      }
      response.success(sum / results.length);
    },
    error: function() {
      response.error("movie lookup failed");
    }
  });
});

I wont go into the API any more here but their docs are pretty good and will explain things much better than me: https://www.parse.com/docs/unity_guide

Parse Unity Sample Project

I have provided a simple Sample Project that hopefully should help with explaining how things work:

The source code for which can be found on github here.

Application Structure

Although Parse.com has a Unity SDK that looks very simmilar to the .Net API, there are some pretty important differences which ill get into later.

Firstly, everyone’s project structure is different and only experience and time will lead you to your own personal preference. For me, I like to setup my project folder like this:

2014-11-10_16-15-46

One folder for the Unity project, one for the Backend and one Common library that is shared between the two.

If you use Visual studio this can all be set into one solution:

2014-11-10_16-17-54

Frontend (ParseUnitySampleProject)

This is the Unity project, you can structure this how you like but I have provided a simple login / signup / logged in menus demo to show how I organise the libraries and code within it:

2014-11-10_16-51-47

Common

The common project contains code that is common to the frontend and backend. This is usually just models that represent the database, in this case its just a simple class GameUser:

[ParseClassName("_User")]
public class GameUser : ParseUser
{       
	[ParseFieldName("playerName")]
	public string PlayerName
	{
		get { return GetProperty<string>("PlayerName"); }
		set { SetProperty<string>(value, "PlayerName"); }
	}

	public bool IsPlayerNameSet { get { return !String.IsNullOrEmpty(PlayerName); } }
}

Every time you build the common project the DLL that gets created is automatically copied into the game thanks to the build task:

2014-11-10_16-22-42

Backend

The backend contains the code that will run on Parse.com and the associated tests:

2014-11-10_16-53-18

I like to use Typescript for my Parse.com backend and so the project is a Typescript project mixed with C# for unit testing. I have provided my unfinished Typescript definition file for parse.com with the project:

2014-11-10_16-54-54

To be continued..

In the next part of this post ill talk more about the specifics of how to interact with the Parse.com API in Unity and some special helpers that I have developed to aid with that.

Tinkering with Google Polymer and Typescript

Tinkering with Google Polymer and Typescript

I recently had the opportunity to experiment with something I have been meaning to play with for a little while, Google’s Polymer.

I first heard about Polymer at Google IO 2014:

I highly recommend watching that video if you want to know more about Polymer but the high level idea is that its a library built on top of the new HTML Web Components and it allows us to write our own custom HTML elements in a way that makes sense.

I really liked the look of it as it reminded me greatly of Adobe’s Flex (MXML) in the way you can write your own components in a declarative manner then bind to various data in the code behind.

So it took me a few days to get my head around things to begin with. One thing I would recommend if you are interested in tinkering with Polymer then first checkout this video:

I wish I had used that to begin with as it would have saved me a whole heap of “is this the correct way to do it?” headaches.

One complication with my setup however is that I really wanted to use Typescript rather than raw Javascript for my code. Well fortunately Visual Studio has really great Typescript support and I was able to create a Typescript project in Visual studio and get cracking immediately.

I ran into an issue with how to use Polymer with Typescript however and there wasn’t too much info on the web out there so hopefully this short guide will help:

1) Create your custom element

I’m using a login element as an example:

login.html

<link rel="import" href="/bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/paper-toast/paper-toast.html">
<link rel="import" href="/bower_components/paper-button/paper-button.html">
<link rel="import" href="/bower_components/paper-input/paper-input.html">
<link rel="import" href="/bower_components/paper-fab/paper-fab.html">
<link rel="import" href="/bower_components/core-icons/core-icons.html">

<polymer-element name="tt-login" attributes="userService">
    <template>

        <style>

            .card {
                margin-top: 64px;
                max-height: 580px;
                max-width: 512px;
                box-shadow: 0 2px 5px 0 rgba(0,0,0,.26);
                border-radius: 2px;
                padding: 20px 16px;
                box-sizing: border-box;
                background-color: white;
            }
			
        </style>

        <div class="card">
            <h1>Login</h1>


            <paper-input floatinglabel label="Your email" type="email" value="{{email}}" error="Input is not an email!"></paper-input>
            <paper-input floatinglabel label="Your password" type="password" value="{{password}}" error="Input is not an email!"></paper-input>

            
            <div horizontal center layout>
                <a href="/#signup"><paper-button disabled?="{{isLoggingIn}}">Signup</paper-button></a>
                <div flex></div>
                <paper-button id="check" on-click="{{login}}" disabled?="{{isLoggingIn}}">Login</paper-button>
            </div>          

            <paper-toast id="errorToast"></paper-toast>
        </div>        

    </template>
    <script src="login.js"></script>
</polymer-element>

Its a pretty simple login element with some binding using some of Google’s paper elements but hopefully you get the idea.

2) Create your custom element’s script

login.ts

class Login extends PolymerElement {

    userService: UserService;

    email: string;
    password: string;
    isLoggingIn: boolean;

    errorToast: PaperToast;

    ready() {
        this.errorToast = this.$.errorToast;
    }

    login() {
        this.isLoggingIn = true;
        this.userService.login(this.email, this.password)
            .then(user => this.onUserLoggedIn(user))
            .fail(err => this.onParseError(err));
    }

    private onUserLoggedIn(u: Parse.User) {
        this.isLoggingIn = false;
        this.fire("logged-in");
    }

    private onParseError(error: Parse.Error) {
        this.isLoggingIn = false;
        this.errorToast.text = error.message;
        this.errorToast.show();
    }

}

Polymer(Login.prototype);

Here we define the variables that we are going to bind to in the element. We also include the “userService” which is an attribute that is a dependency passed into the element.

Note that im able to use this.$ to access the “errorToast” element by ID. Im able to do this because Login extends a class I wrote called PolymerElement:

class PolymerElement {
    $: any;
    style:any;
    fire(eventname: string, payload?: any) { }
    addEventListener(eventName: string, handler: (e : CustomEvent) => void) { }
} 

For now it a bit of a hack to get around the fact that Typescript requires that you implement all elements in an interface so I cant just do “class Login implements HTMLElement”.

Note also the call to Polymer:

Polymer(Login.prototype);

We must pass the prototype into the call then do our variable initting in the ready() function.

3) Use the element

Now we can use it pretty easily:

<!DOCTYPE html>
<html>
<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
    <title>Login Example</title>
        
    <script src="bower_components/platform/platform.js"></script>

    <!-- This is only needed because of the Typescript interface problem! -->
    <script src="lib/polymer_utils.js"></script>

	<!-- Our login element -->
    <link rel="import" href="login.html">

</head>
<body fullbleed layout vertical unresolved>
	<userService id="userService"></userService>
    <login userService="{{$.userService}}"></login>
</body>
</html>

I hope that helps other that are looking to do their own tinkering with Typescript and Polymer!