tag:blogger.com,1999:blog-28060968923012985152024-03-12T17:06:28.454-07:00Prime31 Facebook Scores and Leaderboards using Social Networking PluginAnonymoushttp://www.blogger.com/profile/11669541265957003386noreply@blogger.comBlogger1125tag:blogger.com,1999:blog-2806096892301298515.post-76088632167312132102015-01-01T23:05:00.000-08:002015-01-02T00:18:37.925-08:00<div dir="ltr" style="text-align: left;" trbidi="on">
We decided to add Facebook scores based Leaderboard in our Unity game <a href="https://www.facebook.com/hitbithacker" target="_blank"><span style="color: orange;">Hit Bit Hacker</span></a> and after a bit of research on how to go about it, we finally decided to go with Prime 31's Social Networking Plugin because of the good experience we've already had using some of their other plugins.<br />
<div>
<br /></div>
<div>
We tried out a tutorial from another site to get this plugin working, but found much of the stuff not</div>
<div>
working, perhaps because the plugin has been updated...several coffee breaks, extensive debugging and logging later we were finally able to get it working in our game !</div>
<div>
<br /></div>
<div>
<b><span style="font-size: large;">What will this tutorial do ?</span></b></div>
<div>
<br /></div>
<div>
1. Initial steps and code to setup facebook for your game.</div>
<div>
<br /></div>
<div>
2. Show you how to submit your high score to facebook.</div>
<div>
<br /></div>
<div>
3. Fetch a leaderboard of scores and pics of all your friends who are also playing this game.</div>
<div>
<br /></div>
<div>
<b><span style="font-size: large;">1. Initial Steps</span></b></div>
<div>
<br /></div>
<div>
Setup your app on facebook developer page and then add those settings in Unity.</div>
<div>
Its pretty much straightforward and Prime 31's page shows how to do it, so we won't go into those details here :- </div>
<div>
<br /></div>
<div>
<a href="https://www.blogger.com/"><span style="color: orange;"><span id="goog_1939655672"></span>https://prime31.com/docs#androidSocial (Android)<span id="goog_1939655673"></span></span></a></div>
<div>
<a href="https://prime31.com/docs#iosSocial (iOS)" target="_blank"><span style="color: orange;">https://prime31.com/docs#iosSocial (iOS)</span></a></div>
<div>
<br /></div>
<div>
Next, add a Gameobject in the Unity scene which will represent your Facebook stuff.</div>
<div>
Lets call it "FacebookLeaderboard". This is is the basic code that needs to be in. We will</div>
<div>
add the score stuff later to this same class : </div>
<div>
<span style="color: #0b5394;"><br /></span></div>
<div>
<div>
<span style="color: #0b5394;">#if UNITY_ANDROID</span></div>
<div>
<span style="color: #0b5394;">using FacebookWrapper = FacebookAndroid;</span></div>
<div>
<span style="color: #0b5394;">#elif UNITY_IPHONE</span></div>
<div>
<span style="color: #0b5394;">using FacebookWrapper = FacebookBinding;</span></div>
<div>
<span style="color: #0b5394;">#endif</span></div>
<div>
<span style="color: #0b5394;"><br /></span></div>
<div>
<span style="color: #0b5394;">public class FacebookLeaderboard : MonoBehaviour {</span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>private string FB_APP_ID = "888888888889XYZ"; // replace with your facebook app id</span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"><br /></span></span></div>
<div>
<span style="color: #0b5394;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>void Awake() {</b></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>FacebookWrapper.init();</span></div>
<div>
<span style="color: #0b5394;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>}</b></span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span style="color: #0b5394;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>void OnEnable() {</b></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>FacebookManager.sessionOpenedEvent += LoginSuccess;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>FacebookManager.loginFailedEvent += loginFailedEvent;</span></div>
<div>
<span style="color: #0b5394;"><br /></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>FacebookManager.reauthorizationSucceededEvent += ReauthSuccess;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>FacebookManager.reauthorizationFailedEvent += reauthorizationFailedEvent;</span></div>
<div>
<span style="color: #0b5394;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>}</b></span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"><br /></span></span></div>
<div>
<span style="color: #0b5394;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>void OnDisable() {</b></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>FacebookManager.sessionOpenedEvent -= LoginSuccess;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>FacebookManager.loginFailedEvent -= loginFailedEvent;</span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>FacebookManager.reauthorizationSucceededEvent -= ReauthSuccess;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>FacebookManager.reauthorizationFailedEvent -= reauthorizationFailedEvent;</span></div>
<div>
<span style="color: #0b5394;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>}</b></span></div>
</div>
<div>
<br /></div>
<div>
We won't be going into the details of login and reauthorization permissions here. </div>
<div>
Once the reauthorization success is done, you can post your score to facebook.</div>
<div>
You need to have "publish_actions" permission for this.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<b><span style="font-size: large;">2. Submit your High Score to Facebook.</span></b></div>
<div>
<br /></div>
<div>
Facebook allows you to store one 32 bit integer value for your app and its not a high or</div>
<div>
a low score - its simply a value. You have to check it in Unity side whether this is </div>
<div>
a high score or a low score and then post it.</div>
<div>
<br /></div>
<div>
Lets say you decide to post a high score. The first thing to do is fetch your already existing</div>
<div>
score on Facebook, so that you can compare if the score that you've made is higher.</div>
<div>
<br /></div>
<div>
Here is how to fetch your score along with it's completion handler : </div>
<div>
<br />
<br />
<span style="color: #0b5394;"><b>void GetMyScore() {</b><span class="Apple-tab-span" style="white-space: pre;"><b> </b> </span></span><br />
<span style="color: #0b5394;"> string request = "me/scores";</span><br />
<span style="color: #0b5394;"> Facebook.instance.graphRequest( request, HTTPVerb.GET, OnGetScoreComplete );</span><br />
<span style="color: #0b5394;"><b>}</b></span><br />
<br />
<span style="color: #0b5394;"><br /></span>
<span style="color: #0b5394;"><b>void OnGetScoreComplete( string error, object result ) {</b></span><br />
<span style="color: #0b5394;"> Debug.Log("OnGetScoreComplete result: " + result);</span><br />
<span style="color: #0b5394;"> Dictionary<string, object> resultData = result as Dictionary<string, object>;</span><br />
<blockquote class="tr_bq">
<span style="color: #0b5394;">// a user might remove the app from facebook settings<br />if(resultData == null) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>Debug.Log("No app found");<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>return;<br />}<br />// a user might remove the app from facebook settings<br />if(resultData.ContainsKey("data") == false) {<br /> Debug.Log("Dictionary does not have data key");<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>return;<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />List<object> dataList = resultData["data"] as List<object>;<br />if(null == dataList) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>Debug.Log("Facebook null list !");<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>return;<br />} </span></blockquote>
<blockquote class="tr_bq">
<span style="color: #0b5394;">// post your first score if never done before<br /> if(0 == dataList.Count) {<br /> PostMyCurrentGameScore();<br /> return;<br />}</span></blockquote>
<br />
<blockquote class="tr_bq">
<span style="color: #0b5394;">Dictionary<string, object> objItem = dataList[0] as Dictionary<string, object>;<br />Dictionary<string, object> userItem = objItem["user"] as Dictionary<string, object>;<br />Int64 score = (Int64) objItem["score"]; <b>// Note! : Prime 31 returns a 64-bit int</b></span> </blockquote>
<blockquote class="tr_bq">
<span style="color: #0b5394;">Debug.Log("My retrieved score from Facebook = " + score);</span> </blockquote>
<blockquote class="tr_bq">
<span style="color: #0b5394;">// no need to post game score if score on fb is more<br />if (score >= myCurrentGameScore) {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>Debug.Log("Score not posted because already higher on Facebook !");<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>GetLeaderBoard();<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>return;<br />} else {<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>PostMyCurrentGameScore();<br />}</span> </blockquote>
<blockquote class="tr_bq">
<span style="color: #0b5394;"><b>}</b></span></blockquote>
<br />
<br />
<b> <span style="color: #0b5394;">void PostMyCurrentGameScore() {</span></b><br />
<span style="color: #0b5394;"><br /></span>
<span style="color: #0b5394;"> string request = "me/scores"; </span><br />
<span style="color: #0b5394;"> var parameters = new Dictionary<string,object>()</span><br />
<span style="color: #0b5394;"> {</span><br />
<blockquote class="tr_bq">
<span style="color: #0b5394;">{ "score", myCurrentGameScore.ToString() }</span></blockquote>
<span style="color: #0b5394;">};</span><br />
<span style="color: #0b5394;"> Facebook.instance.graphRequest( request, HTTPVerb.POST, parameters, OnPostScoreComplete );</span><br />
<span style="color: #0b5394;"><b>}</b></span><br />
<blockquote class="tr_bq">
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"></span></span></blockquote>
<br />
<b> <span style="color: #0b5394;">void OnPostScoreComplete( string error, object result ) {</span></b><br />
<blockquote class="tr_bq">
<span style="color: #0b5394;">Prime31.Utils.logObject( result );<br />GetLeaderBoard();</span> </blockquote>
<b> <span style="color: #0b5394;">}</span></b><br />
<blockquote class="tr_bq">
<span class="Apple-tab-span" style="white-space: pre;"> </span></blockquote>
</div>
<div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span></div>
</div>
<div>
<b><span style="font-size: large;">3. Fetch a Leaderboard of scores and pics of friends</span></b></div>
<div>
<b><span style="color: #0b5394;"><br /></span></b>
<b><span style="color: #0b5394;">public void GetLeaderBoard() {</span></b></div>
<div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>string request = "/" + FB_APP_ID + "/scores"; // get friend scores</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Facebook.instance.graphRequest( request, OnLeaderboardComplete );</span></div>
<div>
<span style="color: #0b5394;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>}</b></span></div>
</div>
<div>
<span style="color: #0b5394;"><br /></span></div>
<div>
<span style="color: #0b5394;"> int m_friendsLoaded = 0;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>int m_friendsCount = 0;</span></div>
<div>
<span style="color: #0b5394;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>void OnLeaderboardComplete(string error, object result) {</b></span></div>
<div>
<span style="color: #0b5394;"><br /></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Debug.Log(" >>> result: " + result);</span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Dictionary<string, object> resultData = result as Dictionary<string, object>;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>List<object> dataList = resultData["data"] as List<object>;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>if(null == dataList) {</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Debug.Log("Facebook leaderboard null list !");</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>return;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>} else {</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Debug.Log("Leaderboard Friend List count = " + dataList.Count);</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>m_friendsCount = dataList.Count;</span></div>
<div>
<br /></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>int index = 0;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>m_friendsLoaded = 0;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>while(index < m_friendsCount) {</span></div>
<div>
<span style="color: #0b5394;"><br /></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Dictionary<string, object> objItem = dataList[index] as Dictionary<string, object>;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Dictionary<string, object> userItem = objItem["user"] as Dictionary<string, object>;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>string userID = userItem["id"] as string;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>string name = userItem["name"] as string;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Int64 score = (Int64) objItem["score"];</span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>StartCoroutine( LoadFriendInfo(index+1, userID , name, score) );</span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>index++;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></div>
<div>
<span style="color: #0b5394;"><b> }</b></span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"><br /></span></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span><b>IEnumerator LoadFriendInfo(int position, string userID, string name, int score) {</b></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>string picURL = "http://graph.facebook.com/" + userID + "/picture?type=small";</span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>WWW www = new WWW(picURL);</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>yield return www;</span></div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: #0b5394;"> </span></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>float elapsedTime = 0.0f;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>while (!www.isDone) {</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>elapsedTime += Time.deltaTime;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>if (elapsedTime >= 5.0f) {</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Debug.Log("Pic fetch time out for" + name);</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>break;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>yield return null;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></div>
<div>
<span style="color: #0b5394;"><br /></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Texture2D texPic = www.texture as Texture2D; <b> // this is the pic you can easily show in Unity</b></span></div>
<div>
<span style="color: #0b5394;"><br /></span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>m_friendsLoaded++;</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>if(m_friendsCount == m_friendsLoaded) {</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>// done fetching all pics, so you can trigger something here.</span></div>
<div>
<span style="color: #0b5394;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></div>
<div>
<span style="color: #0b5394;"><b>}</b></span></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<b><span style="color: #444444; font-size: large;">Thats about it!</span></b></div>
<div>
<b><span style="color: #444444; font-size: large;"><br /></span></b></div>
<div>
<b><span style="color: #444444; font-size: large;">Here is how the Leaderboards look in Hit Bit Hacker </span></b></div>
<div>
<b><span style="color: #444444; font-size: large;"><br /></span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvSvqfMiItgrA9cxZ2MqrQSA5g2utpA5mzfQSKufp3Kc6wZwoaxBZMksb3KJT_mO6Vqsoh2wJyUwrYTaXJgS00xubEtT4skcVzr9iYxBwl60UtvlwxD0d2jZcffEsfryPpXUjVEZLcVZE/s1600/2015-01-02_12-31-41.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvSvqfMiItgrA9cxZ2MqrQSA5g2utpA5mzfQSKufp3Kc6wZwoaxBZMksb3KJT_mO6Vqsoh2wJyUwrYTaXJgS00xubEtT4skcVzr9iYxBwl60UtvlwxD0d2jZcffEsfryPpXUjVEZLcVZE/s1600/2015-01-02_12-31-41.png" height="320" width="180" /></a></div>
<div>
<b><span style="color: #444444; font-size: large;"><br /></span></b></div>
<div>
<b><span style="color: #444444; font-size: large;"><br /></span></b></div>
<div>
<b><span style="color: #444444; font-size: large;"><br /></span></b></div>
<div>
<b><span style="color: #444444; font-size: large;">To get a better idea, we highly recommend checking it in action:</span></b></div>
<div>
<b><span style="color: #444444; font-size: large;"><br /></span></b></div>
<div>
<b><span style="font-size: large;"><span style="color: #444444;">[Android] </span></span></b><br />
<b><span style="font-size: large;"><a href="https://play.google.com/store/apps/details?id=com.TwoPi.HitBitHacker&hl=en"><span style="color: orange;">https://play.google.com/store/apps/detailsid=com.TwoPi.HitBitHacker&hl=en</span></a></span></b></div>
<div>
<b><span style="font-size: large;"><span style="color: #444444;">[iOS] (Facebook scores will get activated by Jan10, 2015) </span><a href="https://itunes.apple.com/app/id948551828"><span style="color: orange;">https://itunes.apple.com/app/id948551828</span></a></span></b></div>
<div>
<b><br /></b></div>
<div>
<span style="color: #444444; font-size: large;"><br /></span></div>
<div>
<div style="text-align: center;">
<b><span style="color: #444444; font-size: x-large;">Happy Facebook scoring to your game !</span></b></div>
</div>
<div>
<b><br /></b></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/11669541265957003386noreply@blogger.com1