6 Ways In Which Playing Jimmy Pataya Is Like Running A Game Studio

While I was thinking about a topic for a new blog post, this came to mind. Playing our game Jimmy Pataya is a lot like running a game studio. How so? Here are 6 ways:

1. You have to be crazy like Jimmy to start a studio.

Jimmy Pataya is the embodiment of Paladin’s founders. Because starting your own game studio without any prior experience is like jumping out of an airplane without a parachute. That goes for the whole team: Working for a small indie game developer is just about the same adrenaline rush as if you were a founder.


2. Keep on dodging the blades.

Running a company requires a lot of dodging of obstacles. You should choose a strategy and stick with it. But don’t be afraid to make hard decisions (turns) and dodge those blades!

.

3. Strap those rockets.

In the game, rockets triple your speed. This can be compared to hiring people to boost production. This increases the workspeed incredibly! But at the same time, you are more likely to make mistakes. Stay sharp.
.

4. Grab the superstars.

Superstars are hard to pick up but worth a lot of points. They can be compared to media exposure or winning awards. Whenever a respected journalist writes about your game, that’s a huge bonus! Winning an award gives the same boost, even if it’s just in your self-confidence. Bring on those bonus points!

5. Don’t forget about the regular stars.

The normal stars are worth less points, but they are plentiful and essential for a high score. These can be compared to the smaller things in life. People tweeting about your game, or a good user review. They may not give as many points as the superstar, but they sure matter!

6. Always wear a helmet

The helmet allows you to crash into a blade without ending your run. It symbolizes the stubbornness and perseverance indie game developers must have. They don’t let a setback get to them. They keep on pushing until they get that high score.

Can you think of any other games that resemble game developers? Please let us know in the comments!

Cheers!
Peter

PS: No idea what Jimmy Pataya is? You can play it right here at www.paladinstudios.com. It’s also available in the Appstore ($0.99) and on Android Market (free with ads).

Facebook and Unity Tutorial – Part Three

A note before you start: This is a Unity tutorial about implementing Facebook in Unity projects. It’s a technical how-to guide for Unity developers who want to use Facebook Connect in their web-apps. If that sounds interesting, read on! If it does not, you should check this out. And stay tuned for other blog posts. ;)

The Facebook game we built in part one and part two works fairly well at the moment, although it’s not very exciting. Facebook profile pictures are visible, and we can store and retrieve highscores successfully. However we also saw Mark Zuckerberg having a very suspicious highscore by rolling 7 with a 6 sided dice. In this part we’ll learn how to modify our own scores, and prevent malicious users from doing so.

But first a disclaimer: Creating a 100% secure application is not possible. Just look at any major game released the last several years, they all include some copy protection but its just a matter of time before they are hacked. Hackers are a very creative, and they will always find new innovative ways to exploit your program and make your life miserable.  So in a way, the only thing you are doing is making it harder for malicious users to cheat in your game, completely preventing it now and in the future is sadly impossible.

Hacking your own game

To understand security you have to step towards the dark side too, and learn how to ‘hack’ your application. We’ll focus on one way how Mark Zuckerberg could have modified his score in this tutorial. There are other subjects of security such as copy protection that arent covered.

Webdevelopers have several tools available to them to debug and test their applications, such as Firebug and the built in Chrome Developer Tools. These tools are vital to a webdeveloper, as they allow insights to websites a normal user wont see. However we, a malicious user, could also use these tools to inspect how an application works and modify its execution, such as modifying scores. I’ll be using Firebug in the following samples, but any other web-debugger will do.

Start Firebug and go to the net tab. This will show any external calls being made, and resources being loaded. If you load the page with the net tab open you’ll see the Unity3d file being loaded, facebook images being requested and even our own webservice being called. Anyone can inspect this and find out where your webservice is located and how you use it. Try it out, play the game with the net tab open and you’ll see the insert_highscore request being made. Malicious users could visit the URL manually, supplying their Facebook id and any score they desire like what we did to test our service!

We need a way to verify that what we send from unity and receive in our backend is untouched and exactly the same. Again, 100% protection is impossible, but we can at least make it harder for the attacker. The way we verify the request is by one-way-hashing the parameters we send, and validating the hash serverside. One way hashing means using a algorithm like MD5 or SHA1 to convert one string in another, but this process is not reversible. For example; the MD5 hash of ‘Monkey’ is “4126964b770eb1e2f3ac01ff7f4fd942“, but ‘Donkey’ will turn into “046d93852f6419ac27a74b4ebcaa32e4“. Eventhough the original is very similar their hash is completely different. We can use this to our advantage by calculating the hash of the data we send, send that along the original data to the server and then compare the hash we got with the one we generate again at the server. For example:

  1. Append the Facebook ID and score, use a seperation character and append another secret key for added security. For example: 100000229612727_4_paladinrules.
  2. Hash the appended data and send it along with the original data. Our sample hash would be 3b707fdc8d8f54c27a543b16a68efcf7.
  3. On the server do the same process, append the data we recieve and our secret key. Verify the hashes are the same.

Now if the evil Mark would attempt to change his score the hashes wont match, and we can reject the request completely. Enough talk; lets implement our theory!

Modify insert_highscore.php to add hashing:

<?php
 mysql_connect('localhost','root',''); //Setup database connection
 mysql_select_db('highscores');
 $score = @$_GET['score'];
 $fbid = @$_GET['fbid'];
 $request_hash = @$_GET['hash'];

 if(!$score || !$fbid || !$request_hash ) //Make sure we get all input
 	die("No fbid, score or hash"); 	

 $data = $fbid . "_" . $score . "_paladinrules"; //Hash it up using our format fbid_score_paladinrules
 $hash = md5($data); //Hash it up!
 if(strtolower($hash) != strtolower($request_hash)) //The hashes are different, the request is invalid.
 {
  echo "Invalid request!";
 } else { //it seems legit, lets insert it!
  mysql_query("INSERT INTO scores (fbid, score) VALUES ('$fbid', $score)");
} ?>

As you can see, we now also expect another GET parameter called `Hash` to be passed and compare that to the hash we calculate. When it matches we happily trust the input and insert it, otherwise we show a message to scare off any attackers. Hashes should be case insensitive because some implementations of MD5 capitalize the output and others dont.

Modify DiceGame’s submitHighscore to include the hash:

    IEnumerator submitHighscore(int score, string fbid)
    {
        string hash = md5(fbid + "_" + score + "_paladinrules");
        WWW webRequest = new WWW("http://localhost/insert_highscore.php?score=" + score + "&fbid=" + fbid + "&hash="+ hash);
        yield return webRequest;

        yield return retrieveHighscores(); //After we submit we'd want an update, perhaps someone else played too!
    }
    private string md5(string input)
    {
        // step 1, calculate MD5 hash from input
        System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
        byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
        byte[] hash = md5.ComputeHash(inputBytes);

        // step 2, convert byte array to hex string
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        for (int i = 0; i < hash.Length; i++)
        {
            sb.Append(hash[i].ToString("X2"));
        }
        return sb.ToString();
    }

It is very similar, albeit MD5 is a bit more tricky but luckily C# is well documented. We hash the parameters using the format we’ve made up, and send it to the server.

Build your game and play it, then try to alter your score as you’ve done before. You’ll see the hashes wont be the same, and your score will be rejected. This approach will keep most script-kiddies out, however its only a matter of time before a malicious user figures your secret format out and would be able to generate the hashes themselves. You could further complicate your security model by for example adding another secret key which is user specific, or using a different hashing algorithm.

Even though we are now secure from some basic forms of attacks, we cant rejoice yet. There are plenty of others ways to hack and cheat in your application, and there are always new ways being explored too. You should be especially scared about SQL Injection, which is the number one most commonly used attack on websites. Although theoretically if you cant alter the values you send to the server, you’d rather be safe then sorry.

This concludes the tutorial about Facebook and Unity. I hope you enjoyed it! Please let us know what you think in the comments or the Unity forum topic.

Tijmen van den Heuvel
Paladin Studios

Facebook and Unity Tutorial – Part Two

 

A note before you start: This is a Unity tutorial about implementing Facebook in Unity projects. It’s a technical how-to guide for Unity developers who want to use Facebook Connect in their web-apps. If that sounds interesting, read on! If it does not, you should check this out. And stay tuned for other blog posts. ;)

In part two of our series about connecting facebook and unity we’ll learn the following:

  • Sending and storing highscores.
  • Retrieving highscores.
  • Display scores and facebook profile picture.
If you havent already, you should read part one first.

To make a game

In order to get a highscore we’ll need to make a game. For the demonstration we’ll be creating something very simple, but you should be able to use the lessons learned to implement facebook and highscores in your own games. We’ll be creating a dice rolling game, where the user has to click a button to roll a random number.

Create a new project and add the following script:

<pre>public class DiceGame : MonoBehaviour
{
    public static string FacebookId = "1"; //We'll link up with FacebookManager later.
    private const int max = 6; //Max score, the sides on the dice
    private string btnText = "Press to roll";
    void OnGUI()
    {
        if (GUI.Button(new Rect(10, 10, 200, 50), btnText))
        {
            int score = UnityEngine.Random.Range(1, max + 1); //Calculate our score.
            btnText = string.Format("You rolled {0}, \nclick to try again.", score);

            StartCoroutine(submitHighscore(score, FacebookId));
        }

    }

    IEnumerator submitHighscore(int score, string fbid)
    {
    	yield return null; //We'll implement this later.
    }
}

Nothing fancy there, just a button that when clicked generates a random number and starts our mysterious submitHighscore coroutine. This method should do a webrequest to insert the highscores, so lets create the webservice first!

Creating the webservices

In order to store our scores we’ll need a webservice with a database. Luckily we already have a webserver running locally, we can use that to test. Start by creating a simple database.

We’ll need to store our users facebook id, score and it would be nice to know the creationdate too. Create your database by going to PHPMyadmin, make a new database called `highscores` and run the following SQL to generate the database:


CREATE TABLE `highscores`.`scores` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`fbid` TEXT NOT NULL ,
`score` INT NOT NULL ,
`creation_date` TIMESTAMP NOT NULL
) ENGINE = INNODB;

Now we have our database setup lets create the script that will insert our highscores; create a new file called insert_highscore.php in your WWW directory.  

<?php

	mysql_connect('localhost','root',''); //Connect to the databsae
	mysql_select_db('highscores');

	$score = @$_GET['score'];
	$fbid = @$_GET['fbid'];

	if(!$score || !$fbid) //Ensure both parameters are passed
		die("No fbid or score");

	mysql_query("INSERT INTO scores (fbid, score) VALUES ('$fbid', $score)"); //Execute the query
?>

The first 2 lines connect to the database server and select the proper database. Next we validate the input, and stop executing if either score or fbid was not supplied. After we’re sure they exist we insert them in the database using SQL.
Great, visit your page at http://localhost/insert_highscore.php?fbid=4&score=1, and verify that there is a new row in the database by going to PhpMyAdmin and clicking on Browse in your scores table.

Now we can insert, we’ll need a way to retrieve the scores too. Create a new page with the name get_highscores.php. We dont want to get all highscores from a user, just the highest one. This is where GROUP BY comes in handy.

<?php

	mysql_connect('localhost','root','');
	mysql_select_db('highscores');

	$scoresQuery = mysql_query("SELECT
									MAX(score) as max_score,
									fbid
								FROM
									scores
								GROUP BY
									fbid
								ORDER BY
									max_score DESC");

	while($scoresRow = mysql_fetch_assoc($scoresQuery))
		echo $scoresRow['fbid'] . ',' . $scoresRow['max_score'] . "\n";

?>

It connects to the database again, and executes the query. It then outputs each row as follows:

fbid,score
fbid,score
etc..

Check it out by going to http://localhost/get_highscores.php. If required you can add more highscores by going back to insert_highscore.php. Try using different facebook id’s too, you’ll see more rows being displayed by get_highscores.

Inserting data

Now we have the webservices ready we should be able to call them from our Unity game.


private Dictionary<string, int> scores; //The key is the facebook id, value is his score.

void Start()
{
    scores = new Dictionary<string, int>();
    StartCoroutine(retrieveHighscores()); //Start out by getting the current scores.
}
IEnumerator submitHighscore(int score, string fbid)
{
	WWW webRequest = new WWW("http://localhost/insert_highscore.php?score=" + score + "&fbid=" + fbid);
	yield return webRequest;

	yield return retrieveHighscores(); //After we submit we'd want an update, perhaps someone else played too!
}
IEnumerator retrieveHighscores()
{
	WWW webRequest = new WWW("http://localhost/get_highscores.php");
	yield return webRequest;

	string[] lines = webRequest.text.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); //Split the response by newlines.

	scores = new Dictionary<string, int>(); //Always reset our scores, as we just got new ones.
	foreach (string line in lines) //Parse every line
	{
		string[] parts = line.Split(',');

		string id = parts[0];
		int score = int.Parse(parts[1]);

		scores.Add(id,score);
	}
}

Great, we call the webpages using Unity’s built in WWW class with the proper GET parameters. Whenever you post highscores it will automaticly retrieve them too. There is some parsing going on again in retrieveHighscores, namely we split them by each line and then by comma.
Our Dictionary contains the scores, with the facebook id as key and their highest score as value.

Drag the script on a gameobject in your scene and try it out in the Editor. Validate everything is working properly by clicking the button a few times and then check if there are new rows added in the database.

Linking Facebook

Our game now stores and retrieves highscores properly , but lets link it up with Facebook. Lets create a FacebookManager to retrieve the ID:

public class FacebookManager : MonoBehaviour
{
    void Start()
    {
        Application.ExternalCall("GetCurrentUser");
    }
    public void GetCurrentUserComplete(string fbid)
    {
        DiceGame.FacebookId = fbid;
    }
}

Stick it on a GameObject named FacebookManager and make a web build. Modify the WebPlayer.html to implement the Facebook SDK:

<script src="http://connect.facebook.net/en_US/all.js"></script>
<script type="text/javascript" src="http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject.js"></script>
<div id="fb-root"></div>

<script type='text/javascript'>

	//Fired when the facebook sdk has loaded
	window.fbAsyncInit = function()
	{
		FB.init(
		{
		  appId      : '171298766297727',
		  status     : true, // check login status
		  cookie     : true, // enable cookies to allow the server to access the session
		  oauth      : true, // enable OAuth 2.0
		  xfbml      : false // dont parse XFBML
		});

		//Get the current login status.
		FB.getLoginStatus(function(loginStatusResponse)
		{
			if(!loginStatusResponse.authResponse) //Not logged in, log him in
				FB.login();
		});

	};

	function GetCurrentUser() //When we are logged in this shows our name.
	{
		FB.api('/me', function(meResponse)	//Do a graph request to /me
		{
			getUnity().SendMessage("FacebookManager", //Game object name, make sure this exists!
									"GetCurrentUserComplete", //Method to call
									meResponse.id); //Our serialized facebook data
		});
	}

	//Load the Facebook JS SDK
	(function(d){
	 var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
	 js = d.createElement('script'); js.id = id; js.async = true;
	 js.src = "//connect.facebook.net/en_US/all.js";
	 d.getElementsByTagName('head')[0].appendChild(js);
	}(document));

	function getUnity()
	{
		if (typeof unityObject != "undefined")
		{
			return unityObject.getObjectById("unityPlayer");
		}
		return null;
	}
	if (typeof unityObject != "undefined")
	{
		unityObject.embedUnity("unityPlayer", "WebPlayer.unity3d", 960, 640);
	}
</script>

<div id='unityPlayer'></div>

Open the page and press the button a few times, then go to your database and you’ll see your Facebook ID inserted correctly!

The next step is to do something with the facebook id’s we store, lets show the user’s profile image. As per the Facebook Graph API you can get a users image with the following url: http://graph.facebook.com/UID/picture/

Change your retrieve highscores to this:

private Dictionary<string, Texture2D> fbProfileImages = new Dictionary<string, Texture2D>();
    IEnumerator retrieveHighscores()
    {
        WWW webRequest = new WWW("http://localhost/fbblog/p2/get_highscores.php");
        yield return webRequest;

        string[] lines = webRequest.text.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);

        scores = new Dictionary<string, int>(); //Always reset our scores, as we just got new ones.
        foreach (string line in lines)
        {
            string[] parts = line.Split(',');

            string id = parts[0];
            int score = int.Parse(parts[1]);

            if (!fbProfileImages.ContainsKey(id)) //Have we already loaded this user before?
            {
                //No, better get our image!
                WWW imageRequest = new WWW("http://graph.facebook.com/" + id + "/picture");
                yield return imageRequest;
                fbProfileImages.Add(id, imageRequest.texture);
            }

            scores.Add(id,score);
        }
    }

And change your OnGUI to:

   void OnGUI()
    {
        if (GUI.Button(new Rect(10, 10, 200, 50), btnText))
        {
            int score = UnityEngine.Random.Range(1, max + 1);
            btnText = string.Format("You rolled {0}, \nclick to try again.", score);

            StartCoroutine(submitHighscore(score, FacebookId));
        }

        float h = 10;
        foreach (var score in scores)
        {
            GUI.Label(new Rect(300, h, 200, 50), score.Value.ToString());

            if (fbProfileImages != null && fbProfileImages.ContainsKey(score.Key))
                GUI.DrawTexture(new Rect(230, h, 50, 50), fbProfileImages[score.Key]);

            h += 60;
        }
    }

The fbProfileImages dictionary keeps track of the profile Textures, they get loaded whenever a new user is found. Build and run the project again, and be amazed how easy it is to retrieve someone’s Facebook profile picture.

A great result, but there’s something fishy. Mark Zuckerberg has rolled 7 with a 6 sided dice! In the next part we’ll find out how he did it, and protect ourself against several common attacks used by malicious users.

Download complete project.

Facebook and Unity Tutorial – Part One

Introduction

A note before you start: This is a Unity tutorial about implementing Facebook in Unity projects. It’s a technical how-to guide for Unity developers who want to use Facebook Connect in their web-apps. If that sounds interesting, read on! If it does not, you should check this out. And stay tuned for other blog posts. ;)

Paladin’s games allow players to play with their friends, using  Facebook. In this 3-part series we’ll learn how to connect our Unity application with Facebook, show highscores of our friends and how to secure our application.

Warning! Tech up ahead, this is not for the feint of heart!

In this introductory post we’ll create a FB application, use the Javascript SDK to retrieve the current user’s friends and display their name in Unity. This task requires some familiarity with webdevelopment, and good understanding of Unity and C#. A sneak preview of the final game we’ll be making can be viewed here.

Setting up your application and development environment

To get started, register your application over at Facebook. Do note you need to have a “developer account”, which means you have to supply your phone number. After creating your application you have to tell Facebook its a webpage, by clicking on Website at Select how your  app intergrates with Facebook. For now you can set your Site URL to http://localhost/. This allows you to test your application locally. Another notable setting is Sandbox mode, in the Advanced tab. When this is on only developers can view the application, this is useful when developing the application. Dont forget to turn it off though!

Because we want to develop locally, we want to run a webserver on our own machine. If you dont have one installed, you can use a simple package like Wampserver or XAMPP. Ensure your webserver is working properly by visiting http://localhost in your browser. We at Paladin mainly use PHP for our backend, but if you feel more comfortable using any other technology (ASP, RoR etc) feel free to use that.

Exploring the Facebook SDK

Now we have that setup, lets play around with the Facebook API. To familiarise ourselfs with the Facebook Graph lets create a sample page that gets all information we want. Facebook works using Graph which allows easy access to all information of a user, as long as he is logged in and has granted you enough permissions. We strongly encourage you to read the documentation thoroughly. We’ll be using the Javascript SDK, you should read through the documentation. For our sample we want to get the current user’s id and name, and his friends. Create an html page in your www-root with the following contents:

<script src="http://connect.facebook.net/en_US/all.js"></script>
<script type="text/javascript" src="http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject.js"></script>
<div id="fb-root"></div> <!-- Required by Facebook -->

<script type='text/javascript'>

	//Fired when the facebook sdk has loaded
	window.fbAsyncInit = function()
	{
		FB.init(
		{
		  appId      : '171298766297727',
		  status     : true, // check login status
		  cookie     : true, // enable cookies to allow the server to access the session
		  oauth      : true, // enable OAuth 2.0
		  xfbml      : false // dont parse XFBML
		});

		//Get the current login status.
		FB.getLoginStatus(function(loginStatusResponse)
		{
			if(loginStatusResponse.authResponse) //There is an authresponse, the user is already logged in and authenticated
			{
				logUserName();
				logFriends();

			} else { //The user was not logged in, allow him to.
				FB.login(function(loginResponse)
				{
					if(loginResponse.authRespsonse) //Did he login successfully?
					{
						logUserName();
						logFriends();
					}
				});
			}
		});

		function logUserName() //When we are logged in this shows our name.
		{
			FB.api('/me', function(meResponse)	//Do a graph request to /me
			{
				alert(meResponse.id + " " + meResponse.first_name); //Show the response
			});
		}

		function logFriends()	//When we are logged in this shows our friends.
		{
			FB.api('/me/friends', function(friendResponse) //Do a graph request to my friends.
			{
				for(var i = 0; i < friendResponse.data.length; i++) //Loop over all my friends
					alert(friendResponse.data[i].id + " " + friendResponse.data[i].name);
			});
		}

	};

	//Load the Facebook JS SDK
	(function(d){
	 var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
	 js = d.createElement('script'); js.id = id; js.async = true;
	 js.src = "//connect.facebook.net/en_US/all.js";
	 d.getElementsByTagName('head')[0].appendChild(js);
	}(document));

</script>

After loading the Facebook library it will check the current user’s login status, and offer a login if he isnt already. When we’re sure we are logged we use the graph request to /me to get information about the current user. Then we request the user’s friends by doing a request to /me/friends. Use a Javascript Debugger such as Firebug and step through the code to understand how it works, and what responses the Facebook api requests give.

Bringing it to Unity

Now we have the information we want in our webpage, lets pass it on to Unity! Unity’s excellent reference manual describes how to send basic messages from and to your game. Lets create a button that will ask the HTML page to get the facebook info. Create a new Unity project and create a new script called FacebookManager. Add the following code:

void OnGUI()
{
    if (GUI.Button(new Rect(10, 10, 100, 24), "Get info"))
         Application.ExternalCall("GetCurrentUser")
    if (GUI.Button(new Rect(10, 44, 100, 24), "Get friends"))
         Application.ExternalCall("GetUserFriends")
}

When the user clicks the button the Javascript function GetCurrentUser is called, simple as that. We already know how to get the information from Facebook, now all we need to do is pass it on to our game. We do this by calling SendMessage to the proper GameObject and Method.  There is however a drawback, SendMessage only supports sending a single parameter to Unity, which is insufficient because we want to send a user’s facebook id and name. Therefore we have to come up with some format to pass both parameters. For larger data structures i’d strongly recommend using JSON, and interpeting it in your game. However, since this is a simple sample, we’ll just come up with our own format as such:

id,name; id, name;

Lets rewrite our basic page into something we can use.

<script src="http://connect.facebook.net/en_US/all.js"></script>
<script type="text/javascript" src="http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject.js"></script>
<div id="fb-root"></div>

<script type='text/javascript'>

	//Fired when the facebook sdk has loaded
	window.fbAsyncInit = function()
	{
		FB.init(
		{
		  appId      : '171298766297727',
		  status     : true, // check login status
		  cookie     : true, // enable cookies to allow the server to access the session
		  oauth      : true, // enable OAuth 2.0
		  xfbml      : false // dont parse XFBML
		});

		//Log the user in when the page loads.
		FB.getLoginStatus(function(loginStatusResponse)
		{
			if(!loginStatusResponse.authResponse) //Not logged in, log him in
				FB.login();
		});

		function GetCurrentUser() //When we are logged in this shows our name.
		{
			FB.api('/me', function(meResponse)	//Do a graph request to /me
			{
				var fbdata = meResponse.id + "," + meResponse.first_name; //As per our format, 'id,name;'

				getUnity().SendMessage("FacebookManager", //Game object name, make sure this exists!
										"GetCurrentUserComplete", //Method to call
										fbdata); //Our serialized facebook data
			});
		}

		function GetUserFriends()
		{
			FB.api('/me/friends', function(friendResponse)
			{
				var fbdata;

				for(var i = 0; i < friendResponse.data.length; i++) //Loop over all my friends
					fbdata += friendResponse.data[i].id + "," + friendResponse.data[i].name + ';';

				getUnity().SendMessage("FacebookManager",
										"GetFriendsComplete",
										fbdata);
			});
		}
	};

	//Load the Facebook JS SDK
	(function(d){
	 var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
	 js = d.createElement('script'); js.id = id; js.async = true;
	 js.src = "//connect.facebook.net/en_US/all.js";
	 d.getElementsByTagName('head')[0].appendChild(js);
	}(document));

	function getUnity() //Default unity functions
	{
		if (typeof unityObject != "undefined")
		{
			return unityObject.getObjectById("unityPlayer");
		}
		return null;
	}
	if (typeof unityObject != "undefined")
	{
		unityObject.embedUnity("unityPlayer", "WebPlayer.unity3d", 960, 640);
	}
</script>

<div id='unityPlayer'></div>

Please note additional work has to be done in case the user declines the request or graph requests fail, but that is outside the scope of the tutorial.

Now we’ve retrieved the data in our page, lets make sure we can accept it in our game. Add this to your script, and attach it to a GameObject called FacebookManager.

    private string user_id; //Facebook id
    private string user_name; //User name
    private Dictionary<string, string> friends; //All the users friends key = id, value = name

    public void GetCurrentUserComplete(string fbdata) //Called by js when the userinfo was retrieved. fbdata looks like 1234,name
    {
        string[] parts = fbdata.Split(',');
        user_id = parts[0];
        user_name = parts[1];
    }
    public void GetFriendsComplete(string fbdata) //Called by js when the friends are retrieved. fbdata looks like 1234,name;5678,name;..
    {
        friends = new Dictionary<string, string>();

        string[] parts = fbdata.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); //we've seperated each user, now get their id and name

        foreach (string user in parts)
        {
            string[] userInfo = user.Split(','); //Split each user on ',' first should be id then name.

            friends.Add(userInfo[0], userInfo[1]);
        }
    }

    void OnGUI()
    {
        if (GUI.Button(new Rect(10, 10, 100, 24), "Get info"))
            Application.ExternalCall("GetCurrentUser");
        if (GUI.Button(new Rect(10, 44, 100, 24), "Get friends"))
            Application.ExternalCall("GetUserFriends");

        GUI.Label(new Rect(200, 10, 200, 24), user_name); //Display name

        if (friends != null) //If we retrieved our friends already
        {
            float h = 10;
            foreach (var friend in friends)
            {
                GUI.Label(new Rect(200, 10 + i * 24, 200, 24), friend.Value);
                h += 24;
            }
        }
     }

The code should be fairly self-explanatory, the parsing part can be a bit tricky as it is very error prone. Any unexpected input will break your application. If you arent sure whats going on, try setting breakpoints and using our friendly Debug.Log method to make some sence of it. All our hard work leads us to this; a screen with our current name and the names of our friends:

Great, now you know how to setup your Facebook development environment, make basic calls to the Graph API and pass the response to Unity. With the knowledge you’ve gained, think you can open a post to wall dialog from unity?

Stay tuned for the next part where we’ll learn how to post highscores, and show the scores and profile pictures of our friends!

Download complete project.

Animations Are Evil, Performance Rules

While working at our upcoming game Momo, I am keeping a close eye on performance. It needs to run smoothly (60fps) on an iPhone 3GS, and that is a constant challenge.

While its great to develop for mobile platforms, it can get tricky when you don’t obey the Golden Performance Rules of Lukas. ;)

There are a some simple rules like:

  • Forget about pixellights, too expensive (although the new hardware is looking promising!)
  • Keep your drawcall count low as graphic state changes are cpu expensive
  • Mark objects that don’t move as static
  • If they move, try to keep ‘em below 300 vertices, it will then be dynamicly batched
  • Don’t instantiate or destroy objects in runtime as memory is slow and it will create hiccups
  • Don’t alpha reject pixels on iOS devices because its slow on tile based rendering, use alpha blend instead
  • Don’t talk about polygon count but vertex count
  • Don’t rely on the 3D modelings package for your total vertex count, use the 3D engine instead as a number of things can influence this number
  • Don’t non-uniform scale your objects in an animation as they won’t be batched

On this last one I have a good example, with some pictures. (yay pictures!)

So here we have a nice cracked rock

In the game it will crack and fall apart

But wait, 2 drawcalls?

The complete asset is only 176 vertices and it should batch! Well it is batched, partially. Lets investigate it. The rock consists of 6 pieces. All using the same material? Check. All under 300 vertices? Check. All scales are uniform? Check. Or is it? Well on start it is but in the animation one of the rocks is slightly scaled in the x and y axis.

Okay, so walk to the artist, I tell him, he frowns, I explain, he frowns, he fixes, all happy.

At the bottomline: performance isn’t only a programmers thing anymore. For mobile, a lot depends on how game assets are created, you can’t get away with sloppyness anymore.

Oh and by the way, if you are an artist and you want to go up a few levels, please please please read the book Creating 3D Game Art for the iPhone with Unity. It will make your and my life a lot easier. It has been written by and for the game artist but even I enjoyed reading it!