Monday 17 February 2014

Technical Post 1: Integrating Facebook into unity C# Part 2

<< Part 1
Note: This is in C#
We should now have the players name from Facebook, so now we will look at how to POST something to Facebook like a score. Where in our game, when the player dies we want to check if their new score is their highest and then we call the HTTP POST method to send their score to Facebook to compare with their friends. We use the following code;
public void setScore()
{
    int score = currentScore;
    var ScoreData =  new Dictionary<string, string>() {{"score", score.ToString()}};
    FB.API("/me/scores", Facebook.HttpMethod.POST, publishActionCallback, ScoreData);
    print ("Score data" + ScoreData);
}
void publishActionCallback(FBResult result)
{
    print ("say something");
}

When the setScore() Method is called a local variable is given the value of the players' score, and then a new variable is created under the Dictionary type which creates the value in a way that the Facebook SDK understands the value that is being sent up. Then we use FB.API to send the value to Facebook, with similar parameters before, but using a HTTP POST instead and adding the var created to the request that will be sent up to Facebook, on successful completion the method will call the Callback method in this case "publishActionCallback(FBResult result)" where FBResult is the data returned by Facebook on completion and the method tells the console to print something to show that the request was successful.

So now we can post scores and get scores, feel free to ask if you are having problems with this, (changing "me?fields=name" for "me/scores") we can now look at getting our friends scores from Facebook. First of all, we must make sure that the permissions for our game allow us to access our friends game data, so we must go to the Facebook Graph explorer and make sure that we have all the needed permissions. (Facebook Graph Link)

If we start by creating an access token for our app, simply by clicking "Get Access Token" and making sure the fields "user_games_activity" and "friends_games_activity" are checked, then create the access token. If we now set the request type to GET and type "me/permissions" and submit, we should see a list of permissions including the ones we just added with a value of 1(meaning true).

The easiest way to find the code for this to work, is to take the Util.cs script for the friend smash (script Link) and copy it into your own project so that you can access the Util directory and use this with MiniJSON to parse the data returned by Facebook and extract only the information you want. It is possible to search the return value as it was a string and look for a string before the one you want and take the string at the end, this would return the section of the string you want, but is not the best for using when you have more than one persons piece of data.

Using the Util.cs script, we can also look at the MainMenu.cs script from the same example (Link) and see how it is implemented into the game. In this case when we call our friends who use the app and have a score we use the following HTTP GET request;
FB.API("/app/scores?fields=score"Facebook.HttpMethod.GETCallbackFriendScores);
This will return an array of our friends scores and Facebook returns the values in descending order where the first value returned has the highest score. This makes it easier for assigning the return values to text within your game or UI.

We now want to look at how we can actually access the array of data, as a relatively beginner programmer, this was difficult for me, as there was little documentation that outlined exactly what I had to do in order to access the information I wanted. The answer is really simple in practice, even if you don't understand what exactly you are doing, if you follow this there should be no problem.

Using the Util.cs script, in our callback method, we create a list of objects to contain the parsed data from the Util method that we are about to call.
We can now use Util.DeserializeScores(result.Text) and assign the result to the list of objects that we have declared. This method will return the scores and names of the players and with that we can start to assemble a high scores table.
Next we can simply go through the list of objects using a "foreach(object score in [Enter list name])" method that will go through the data and write allow us to access it for manipulation and use in our game.
The code below is used within our foreach loop to get and assign the users name, id and score as a local string variable to make it easier to use.
var entry = (Dictionary<string,object>) score;
var user = (Dictionary<string,object>) entry["user"];
string name = (string)user["name"];
string userId = (string)user["id"];
string score = (string)entry["score"];

I have added some of my script to the next page for reference, if you want an example of how this will work, I cannot add screen shots of it working at this time, but will add them when available

Check the full method to get scores and post scores below

public void getScore()
{
    FB.API("me/scores", Facebook.HttpMethod.GET, CallbackMyScore);
}
public void CallbackMyScore(FBResult result)
{
    FriendScores = new List<object>();
    List<object> FriendScoresList = Util.DeserializeScores(result.Text);
      
    foreach(object score in FriendScoresList)
    {

        bool fbScoreExists = false;
        var entry = (Dictionary<string,object>) score;
        var user = (Dictionary<string,object>) entry["user"];
          
        string userId = (string)user["id"];
        if (string.Equals(userId,FB.UserId)) {

            fbScoreExists = true;
            int playerHighScore = getScoreFromEntry(entry);
            if (currentScore > playerHighScore)
            {
                setMyScore();
            }
            else return;

        }
    }

    if(!fbScoreExists)
        setMyScore();
}



Now that we have players names and scores used in our game, we wanted to get their profile picture within the high scores table, so that our players could recognise who they had beat easier, to do this using a HTTP GET method every time would have been a lot more complex than it needed to be, so what I did was use a simple url get request using the WWW object type and receive a texture directly from Facebook. With the way that our high scores table is written we had to wait until the table was formed and formatted until the pictures were assigned to reduce calls to the web, so I added in some temp string variables that will hold the id of each position in the table.

string url = "http://graph.facebook.com/" + idPos1 + "/picture";
WWW www = new WWW(url);
yield return www;
Pic1Script.image = www.texture;

*this is using OTSprite, the texture assign for other systems can be found online easily
This simply uses the id for position 1 in the table to get a texture from Facebook and assign that texture to the desired object in the scene.

One last piece of code that is useful is the check to see if the current object being looked at is the current player. To do this we take the userId string and compare it using our FB.userId method to see if they are identical.

See next post for full example code

14 comments:

  1. Hy. I'm developing an android app and i'am using the facebook sdk for unity to post and get scores to/from facebook. I have a problem with posting score. Up on that page you gave an exemple code for posting score but i think it is a problem with 'var ScoreData = new Dictionary<string, string() {{"score", score.ToString()}};' or with the declaration of the funcition. Can you check again to help me please? Thank's in advance!

    ReplyDelete
    Replies
    1. Hi, have you worked through the first part of this, that will help you to set up your app as a facebook developer and the initial step of understanding how it works. make sure you have the following libraries in your code also
      using System.Collections.Generic;
      using Facebook.MiniJSON

      Delete
    2. Thank you for your fast reply! Yes, i have forgotten to insert those libraries. What a noob mistake...whatever. But i get an error on the line with: 'var ScoreData = new Dictionary'
      '.

      Delete
    3. The facebook sdk is set up. I compiled the facebook example project and tested on my android device and it's working fine. I can login, I can take a screenshot and upload it etc... But I have started to work on my own C# script to learn how the facebook sdk works. I made 2 buttons for login and logout and it works. And now I want to post and retrieve a score on my facebook account like i would be a player and i get that error...

      Delete
    4. I got the problem... It's not 'var ScoreData = new Dictionary() {{"score", score.ToString()}};'.
      The problem is: Dictionary() because in your code is without '>'. Whatever, thanks for your reply!

      Delete
    5. Thanks for that, I will correct it now!

      Delete
    6. Now I have another problem: Using 'print' the compiler says: Score dataSystem.Collections.Generic.Dictionary`2[System.String,System.String]
      UnityEngine.MonoBehaviour:print(Object). It should write the "score" + int, no?...

      Delete
    7. I do not think that this part should be too important for it to work. I was just using this as a way to see that the code was being reached without using breakpoints. it is equivalent to printing scoreData.toString(), if you wanted to print the score that was passed to facebook, you should use what you suggested

      Delete
    8. I don't want to say that is an error or something like that, I just think the score haven't been stored on facebook... i don't know. It would be nice if you give me the function to retrieve the score to check, please.

      Delete
    9. Sorry, you have two options for this, you can do it through your code, as above I use

      public void getScore()
      {
      FB.API("me/scores", Facebook.HttpMethod.GET, CallbackMyScore);
      }
      Do you need the full callback method for getting the score, I will add it to the post to make it easier for other people

      Or (the easier method) you can use the Facebook Graph API Explorer, making sure that your application is selected and use the GET request me/scores and it should tell you your score that was sent to facebook
      https://developers.facebook.com/tools/explorer/145634995501895/?method=GET&path=me%2Fscore

      Delete
    10. Thanks ;) I feel i'm going crazy but i try to understand how the facebook sdk works. Thank you for your replies.

      Delete
    11. How can I display the score from Facebook on GUI?

      Delete
    12. I don't have too much experience with on GUI, sorry, but if you check the example code for high scores in part 3 you should be able to see how to get the score, name and id of each of your friends in string form, and then apply it to GUI

      Delete
  2. I forgot to say that i'm a beginner in working with facebook sdk in unity3d. :)

    ReplyDelete