November 2014 Posts

Working with Parse.com in Unity – Part 3 – Tests, Typescript and Common Code

Working with Parse.com in Unity – Part 3 – Tests, Typescript and Common Code

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 how to use Parse.com in Unity itself, in this post I want to talk about to to go about writing backend code.

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

Environment

I briefly talked about App structure in my first post. I like to use use Visual Studio with Typescript and C# for my Backend as they all play nicely together an produce a hassle free way of coding up the backend.

I like to have the Parse command line app running in develop mode (parse develop “Parse Unity Sample”) at the same time so I can see whats happening on the server when I call it, and it allows for very quick iterations:

2014-11-11_08-39-16

Typescript

I have talked a lot in the past about my love for Typescript and so I love to use it whenever I can. Parse lets you run Javascript code on the server so I use Typescript that compiles to Javascript. To get it to work I first create a Typescript project that has been setup with CommonJS as the module system:

2014-11-11_08-40-46

I then make sure all the code is contained withing the /cloud folder (so that the require() works):

2014-11-11_08-45-22

It works well, particularly when combined with my (not yet finished) Typescript definition for Parse which provides type safety for as much as possible:

2014-11-11_08-47-02

For example, the code that is run before a User is saved looks like:

// Force this TS file to become a module
export var x = 2;

Parse.Cloud.beforeSave("_User", (request, response) => {

    // Must have a player name
    if (request.object.get("playerName") == null || request.object.get("playerName") == "")
        return response.error("Must supply a player name when creating a new user");

    // Email and username must equal
    if (request.object.get("email") != request.object.get("username"))
        return response.error("Username and email address must be equal");

    // All done
    response.success();
});

Testing

Because there is no way to run Parse cloud code offline, all tests must run on code that runs on the Parse servers. At first this sounded really nasty to me and almost put me off using Parse all together but once I realised that I could just create another App for testing and structure my test in such a way that I could isolate each test, I grew to like it, I actually really enjoy writing these tests now.

I like to use NUnit with the Parse .NET SDK for the testing because it lets us use some more advanced C# features such as async / await which the Unity SDK hasn’t got access too, and more importantly it returns the server error messages (unlike Unity) which we can test against.

To get started just create a Test class in your Typescript project (surprisingly Typescript projects work well C# within them in Visual Studio) and start testing:

namespace ParseUnitySampleBackend.Tests
{
    [TestFixture]
    public class SaveUserTests
    {
        [SetUp]
        public async void Init()
        {
            TestingHelpers.InitParse();
            ParseUser.LogOut();
        }

        [Test]
        [ExpectedException(ExpectedMessage = "Must supply a player name when creating a new user")]
        public async void RequiresPlayerName()
        {
            var user = new GameUser()
            {
                Username = TestingHelpers.GetRandomUserEmail(),
                Password = "a"
            };
            await user.SignUpAsync();
        }
		
	...

I included some simple helpers that I like to use for testing which setup Parse before each test.

If you use Visual Studio’s Test Explorer with the parse command line you can get really good feedback on what is happening on the server:

2014-11-11_08-59-15

Common Code

Because I write my tests in C# and my Unity code is in C# I would like to share my common code between the two projects. Unfortunately simply splitting the project out into a library project then including it as a reference in the testing project doesn’t work because Unity requires a different compiler (Unity 3.5 subset on mono) and thus when you try to add that as a reference you get errors related to invalid assemblies:

2014-11-11_09-03-05

The solution I found is to use a little known trick of linking source. To do this select the “Models” folder from the common project and while holding Control and Shift drag it into the Backend project, you should note that the cursor changes to a little shortcut icon and when in the backend project the file icons now have a shortcut icon to indicate they are linked:

2014-11-11_09-05-26

This means that files are linked to the Common project so they are included in compilation and any changes you make to those files in either the Common project or Backend project will be reflected in the other.

This is perfect as it now lets us compile the same files using a different compiler and version of Parse.

Conclusion

Well thats it for my three part post on how to get started using Parse in Unity. I hope it helps some people, please do leave me a comment or email me: mike.cann@gmail.com if you have any questions.

Happy coding!

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.