この記事は CAMPHOR- Advent Calendar 2015 8日目の記事です。
「イケてるSNSクライアントアプリを作ろう」と言われた時、皆さんは何で開発しますか?
Swift?Java?それも良いかもしれないですね。ですが、敢えて言わせていただきましょう。それ、学習コスト高くないですか?
言語だけでなく、IDEにさえ高い学習コストが求められるこれらは、多くの場合志半ばでの挫折を招いてしまうでしょう。
ここでの最もNiceな回答をお教えします。「Unity」それが正解です。
学習コストが極めて低いUnityで開発すればSNSクライアント程度、3日もあれば完成するでしょう。
ということで本日は、UnityからTwitterやFacebookのAPIを叩く方法を皆様に伝授しようと思います。
UnityでTwitter
まず、Twitterのやり方からご説明して行きましょう。
インポート
以下のAssetを使用します。
適当なプロジェクトを作成し、AssetStoreでこのAssetを探してインポートして下さい。
インポートするとこんな感じになるはずです。
これらのファイルがAssets/
直下にあるのが少し気持ち悪いので、Assets/Plugins/LetsTweetInUnity/
のようなディレクトリを作り、移動させると良いでしょう。
ライブラリの修正
さて早速このAssetを使っていきたいのですが、Let's Tweet In Unityはインポート直後にエラーを吐くステキ仕様になっております。涙がちょちょぎれますね。
どうも、Let's Tweet In UnityではWWWクラスのコンストラクタ引数headers
にHashTable
型を使用しているようです。これは今まで非推奨として扱われていたのですが、どうやらいつの間にかHashTable
型を許容しない仕様になっていたようですね。(各所文献を見た感じでは、割と最近の出来事のようです)
諸行無常。変わってしまったものは仕方ないので、HashTable
型のheader
をDictionary<string, string>
型に変換してあげましょう。
以下のようにTwitter.cs
を書き換えてください。
136行目, 149行目, 194行目
//var headers = new Hashtable(); Dictionary<string, string> headers = new Dictionary<string, string>();
これでOKです。各行それぞれ同じように書き換えてください。
書き換えて保存すると無事エラーが消えるはずです。
テストシーンの作成
エラーも修正できたところでAPIをテストするためのSceneを作成していきましょう。適当にTwitterAPITest
のようなSceneを作成すると良いでしょう。
作成出来たら、GameObjectを配置していきます。このSceneではUIしか使わないので、SceneViewを2D modeにしておくと作業が進めやすいかと思われます。
まず、以下のように要素を配置していきます。
上から順に説明していきます。
GetPINButton (Button)
PINCode取得用のButton
InputPINField (InputField)
取得したPINCodeを入力するInputField
AuthPINButton (Button)
PINCode認証用のButton
です。
続いて、Tweet用の要素を配置していきます。 Tweet文のInputFieldですが、沢山行数を打てるように広めのものにしたいですよね。ただ、雑にScaleで拡縮すると全てが縦長なだけのInputFiledが完成するので、拡縮する際は、UI拡縮ツールを使うようにしましょう。
UI拡縮ツールは上の画面で言う、SceneViewの左上にある、選択されている小さいボタンです。 TweetButtonもつけると以下のようになります。
要素の説明をしていきます。
InputTweetField (InputField)
Tweet文を入力するInputField
TweetButton (Button)
Tweet用のButton
UIの設置はこれで終了です。最後に、TwitterAPIを叩くScriptを付与させたGameObjectを作成しましょう。
Hierarchy -> Create -> Create Empty
で空GameObjectを作成して、名前をTwitterComponent
にします。
その後、Assets/Scripts/
などのディレクトリを作成し、そこで右クリック、Create-> C# Script
でC#ScriptFileを作成します。名前はTwitterComponentHandler
にします。
ScriptFileが作成できたら、TwitterComponent
にアタッチしましょう。
これでSceneの準備は完了です。
Twitterアプリケーションの作成
続いて、APIをテストするためにTwitterApplicationを作成してください。
Twitter APIの使い方まとめ
この記事が大変分かりやすいかと思われます。Consumer Key
とConsumer Secret
を使うので、それらが記載されたページを開いておいて下さい。
コードの記述
ではあらかたの準備が出来たので、早速コードを書いていきましょう。TwitterComponentHandler.cs
を開いて下さい。
using ディレクティブ
まずusing ディレクティブを記述しましょう。デフォルトでUnityEngine
とSystem.Collections
が記述されていますが、これに加えて今回はUIクラスの機能を頻繁に使用するので、UnityEngine.UI
もここに追記しましょう。
using UnityEngine; using UnityEngine.UI; using System.Collections;
こうなりますね。
変数宣言
続いて、変数の記述をしていきましょう。ココらへんで脳みそを使いたくないので、Demo.csからいい感じにパクります。健康的なコーディングはパクリによって保証されます。
public class TwitterComponentHandler : MonoBehaviour { public GameObject inputPINField; public GameObject inputTweetField; private const string CONSUMER_KEY = "先ほど作成したTwiiterアプリのConsumer Key"; private const string CONSUMER_SECRET = "先ほど作成したTwiiterアプリのConsumer Secret"; Twitter.RequestTokenResponse m_RequestTokenResponse; Twitter.AccessTokenResponse m_AccessTokenResponse; const string PLAYER_PREFS_TWITTER_USER_ID = "TwitterUserID"; const string PLAYER_PREFS_TWITTER_USER_SCREEN_NAME = "TwitterUserScreenName"; const string PLAYER_PREFS_TWITTER_USER_TOKEN = "TwitterUserToken"; const string PLAYER_PREFS_TWITTER_USER_TOKEN_SECRET = "TwitterUserTokenSecret"; const string PLAYER_PREFS_TWITTER_TWEETED_IDS = "TwitterTweetedIDs"; // Use this for initialization void Start () { }
input
接頭辞で始まるものには、それぞれ対応するInputFieldをUnityエディタ上で設定してあげます。
CONSUMER
接頭辞で始まるものには、TwitterアプリのConsumerKey, Secretを格納しておきます。
m_RequestTokenResponse
とm_AccessTokenResponse
はそのままです。認証をしていき、それぞれのTokenが格納されていく予定です。
PLAYER_PREFS
接頭辞で始まるものは、PlayerPrefsへアクセスするためのkeyが格納されています。Demoでは一度取得したTokenは、PlayerPrefsに格納するように作られています。
毎度PINを入力させてログインさせる、というケースはあまりないと思われるので、そのままDemoに倣いましょう。
OnClickEventの定義
続いて、各ボタンのOnClickEventを定義していきましょう。
void Update(){}
以下に記述します。
// Update is called once per frame void Update () { } /* OnClick Event */ public void OnClickGetPINButon () { StartCoroutine(Twitter.API.GetRequestToken(CONSUMER_KEY, CONSUMER_SECRET, new Twitter.RequestTokenCallback(this.OnRequestTokenCallback))); } public void OnClickAuthPINButon () { string myPIN = inputPINField.GetComponent<InputField> ().text; StartCoroutine(Twitter.API.GetAccessToken(CONSUMER_KEY, CONSUMER_SECRET, m_RequestTokenResponse.Token, myPIN, new Twitter.AccessTokenCallback(this.OnAccessTokenCallback))); } public void OnClickTweetButon () { string myTweet = inputTweetField.GetComponent<InputField> ().text; StartCoroutine(Twitter.API.PostTweet(myTweet, CONSUMER_KEY, CONSUMER_SECRET, m_AccessTokenResponse, new Twitter.PostTweetCallback(this.OnPostTweet))); }
ButtonComponentのOnClickにEventを設定するには、publicな関数にしてあげる必要があります。
基本的にTwitter.API
で定義されているコルーチンを呼び出すことで、TwitterAPIを叩けるようになっています。
詳しく知りたい方は、Twitter.cs
を読む事をオススメします。さほど量もないので、ある程度の知識があればそれほど時間はかからないでしょう。
コールバック関数の定義
さて、先ほどのOnClickEventですが、それぞれ引数にコールバック関数を取っているので、コールバック関数を記述していきましょう。
public void OnClickTweetButon () {}
以下に記述していきます。
/* Callback Event */ void OnRequestTokenCallback(bool success, Twitter.RequestTokenResponse response) { if (success) { string log = "OnRequestTokenCallback - succeeded"; log += "\n Token : " + response.Token; log += "\n TokenSecret : " + response.TokenSecret; print(log); m_RequestTokenResponse = response; print (response.Token); print (response.TokenSecret); Twitter.API.OpenAuthorizationPage(response.Token); } else { print("OnRequestTokenCallback - failed."); } } void OnAccessTokenCallback (bool success, Twitter.AccessTokenResponse response) { if (success) { string log = "OnAccessTokenCallback - succeeded"; log += "\n UserId : " + response.UserId; log += "\n ScreenName : " + response.ScreenName; log += "\n Token : " + response.Token; log += "\n TokenSecret : " + response.TokenSecret; print(log); m_AccessTokenResponse = response; PlayerPrefs.SetString(PLAYER_PREFS_TWITTER_USER_ID, response.UserId); PlayerPrefs.SetString(PLAYER_PREFS_TWITTER_USER_SCREEN_NAME, response.ScreenName); PlayerPrefs.SetString(PLAYER_PREFS_TWITTER_USER_TOKEN, response.Token); PlayerPrefs.SetString(PLAYER_PREFS_TWITTER_USER_TOKEN_SECRET, response.TokenSecret); } else { print("OnAccessTokenCallback - failed."); } } void OnPostTweet (bool success) { print("OnPostTweet - " + (success ? "succedded." : "failed.")); }
それぞれが、それぞれのコールバック関数として対応しています。
success
とresponse
でそれぞれ結果を受け取れるようになっています。
基本的なコードはこれで完成です。
エディタ上での設定
最後に、エディタ上で各設定を行っていきましょう。
publicなGameObject型変数の値を設定
publicなGameObjectとして宣言した変数に値を設定していきましょう。InputField系ですね。
これでOKです。
OnClickEventの設定
続いて、ButtonにOnClickEventを設定していきます。
ほぼ同じ作業なので、GetPINButton
を例にあげて説明していきます。
まずHierarchyView上でGetPINButton
をクリックし、Componentを表示させます。
続いて、Button(Script)
内にある、OnClickの右下にある+をクリックしてください。
None(Object)
という項目が出てくるので、HierarchyView内のTwitterComponent
をドラッグして設定しましょう。
設定すると、No Function
と書かれていたところが選択可能になります。そのプルダウンメニュー内から TwitterComponentHandler -> OnClickGetPINButon ()
を選択します。
これで、GetPINButton
のOnClickEventとして、OnClickGetPINButon ()
が設定されました。
同じように、AuthPINButton
にOnClickAuthPINButon ()
、TweetButton
にOnClickTweetButon ()
を設定してあげましょう。
完成
これで、TwitterのPINコード認証が出来、Tweetが出来るSceneが完成しました!
使い方
まず、GetPINCpdeをクリックすると、アプリケーションを認証するかどうかの画面に飛ばされるので、そこで承認をする。
すると、PINコードが表示されるので、Unityに戻り、PINコードを入力し、AuthPINCodeをクリックする。successとprintされたら成功です。
あとは、Tweet文を適当に入力し、Tweetボタンをクリックしましょう。successとprintされたら、無事ツイートが行われているはずです。
これで最低限の機能が実装できました。ここからは、複数のテストケースを元に、実装方法を見ていきましょう。
OnPostTweetでresponseを取得する。
Tweetした後、そのTweetのidを取得したい、という事はよくあるでしょう。しかし、現状OnPostTweetではsuccessしたか否かという情報しか参照出来ません。
もし、OnPostTweetでresponseを受け取りたい場合は、Twitter.cs
を書き換える必要があります。
まず、PostTweetCallback
の定義部を書き換えましょう。
// public delegate void PostTweetCallback(bool success); public delegate void PostTweetCallback(bool success, string response);
こうすることで、callbackにresponseを渡せるようになりました。では実際にPostTweet()
内でcallbackにresponseを渡す処理を書きましょう。
public static IEnumerator PostTweet(string text, string consumerKey, string consumerSecret, AccessTokenResponse response, PostTweetCallback callback) { if (string.IsNullOrEmpty(text) || text.Length > 140) { Debug.Log(string.Format("PostTweet - text[{0}] is empty or too long.", text)); callback(false, ""); } else { Dictionary<string, string> parameters = new Dictionary<string, string>(); parameters.Add("status", text); // Add data to the form to post. WWWForm form = new WWWForm(); form.AddField("status", text); // HTTP header Dictionary<string, string> headers = new Dictionary<string, string>(); headers["Authorization"] = GetHeaderWithAccessToken("POST", PostTweetURL, consumerKey, consumerSecret, response, parameters); WWW web = new WWW(PostTweetURL, form.data, headers); yield return web; if (!string.IsNullOrEmpty(web.error)) { Debug.Log(string.Format("PostTweet - failed. {0}\n{1}", web.error, web.text)); callback(false, web.error); } else { string error = Regex.Match(web.text, @"<error>([^&]+)</error>").Groups[1].Value; if (!string.IsNullOrEmpty(error)) { Debug.Log(string.Format("PostTweet - failed. {0}", error)); callback(false, web.error); } else { callback(true, web.text); } } } }
こうですね。これでPostTweetのコールバック関数にresponseが渡されるようになりました。
ついでに、TwitterComponentHandler
も書き換えましょう。
void OnPostTweet (bool success, string response) { print("OnPostTweet - " + (success ? "succedded." : "failed.")); if (success) { print (response); } }
この時点でDemo.csが死を迎えることになります。削除するか、上と同じようにOnPostTweetの第二引数にresponseを与えてあげましょう。
これで、ツイート成功時にresponseがprintされるようになりました。
しかし、ただのstringとして渡されてくるので長文のJSONがダダダッとconsoleに表示され、かなり辛いものを感じることになります。
JSONをパースしよう
このままではidの取得も一苦労ですので、responseをJSONとしてパースし、もっと楽に扱えるようにしましょう。
Unityで扱えるJSONパースのライブラリとしてオススメするのはSimpleJSON
というものです。
以上のリンクにあるDownloadの項からライブラリをダウンロードして下さい。
ダウンロードしたフォルダ内にSimpleJSON.unitypackage
というものがあるはずです。これをダブルクリックしてインポートしましょう。
インポートが完了したら、Assets/Plugins/SimpleJSON/
などというディレクトリを作成し、そこにインポートして出てきたファイル郡を移動させましょう。
これでインポートは完了です。早速スクリプト内で扱ってみましょう。
まず、usingディレクティブを記述します。
using UnityEngine; using UnityEngine.UI; using System.Collections; using SimpleJSON;
これで、このスクリプトファイル内でSimpleJSONライブラリの関数が扱えるようになりました。
JSON.Parse(JSON文字列)
でJSON文字列をJSONObjectにパース出来ます。
ここでは、responseを渡せば良さそうですね。実際にやってみましょう。
void OnPostTweet (bool success, string response) { print("OnPostTweet - " + (success ? "succedded." : "failed.")); if (success) { var json = JSON.Parse (response); print (json ["id"]); } }
これでresponse内にあるidを無事に取得できました!
SimpleJSONは他にも様々な関数があります。種類や使い方は、SimpleJSON を読むと良いでしょう。
他のAPIを叩く
認証やPostTweetだけではなく、もっと色々なAPIを叩きたいと思うこともあるでしょう。
そこで、GET statuses/user_timeline
を叩く処理を実装しながら、他のAPIを叩く処理の実装方法を学んでいきましょう。
基本的にはPostTweet()
を真似しつつ、適宜渡すheadersなどを変えると大体いい感じに仕上がります。
なので、まずはPostTweetをコピペして、関数名などを変えましょう。
private const string GetUserTimelineURL = "https://api.twitter.com/1.1/statuses/user_timeline.json"; public static IEnumerator GetUserTimeline(string text, string consumerKey, string consumerSecret, AccessTokenResponse response, GetUserTimelineCallback callback) { if (string.IsNullOrEmpty(text) || text.Length > 140) { Debug.Log(string.Format("GetUserTimeline - text[{0}] is empty or too long.", text)); callback(false, ""); } else { Dictionary<string, string> parameters = new Dictionary<string, string>(); parameters.Add("status", text); // Add data to the form to post. WWWForm form = new WWWForm(); form.AddField("status", text); // HTTP header Dictionary<string, string> headers = new Dictionary<string, string>(); headers["Authorization"] = GetHeaderWithAccessToken("POST", GetUserTimelineURL, consumerKey, consumerSecret, response, parameters); WWW web = new WWW(GetUserTimelineURL, form.data, headers); yield return web; if (!string.IsNullOrEmpty(web.error)) { Debug.Log(string.Format("GetUserTimeline - failed. {0}\n{1}", web.error, web.text)); callback(false, web.error); } else { string error = Regex.Match(web.text, @"<error>([^&]+)</error>").Groups[1].Value; if (!string.IsNullOrEmpty(error)) { Debug.Log(string.Format("GetUserTimeline - failed. {0}", error)); callback(false, web.error); } else { callback(true, web.text); } } } }
GetUserTimelineURL
はちゃんとそのAPIに対応したURLに変更しています。
その他にも、適宜PostTweet
のように書かれているところをGetUserTimeline
に置き換えています。
また、GetUserTimeline用のcallback関数を定義しました。以下のように記述して下さい。
public delegate void RequestTokenCallback(bool success, RequestTokenResponse response); public delegate void AccessTokenCallback(bool success, AccessTokenResponse response); public delegate void PostTweetCallback(bool success, string response); public delegate void GetUserTimelineCallback(bool success, string response);
これで土台が出来上がりましたね。ただ、POSTリクエスト用の関数を持ってきたので少々不具合があります。
まず、WWWFormにparamaterを渡して…という事をしているので、普通にパラメーターをURLとしてビルドしてくれる関数を用意しましょう。
UrlEncode()
以下に記述してください。
private static string BuildURL(string baseURL, Dictionary<string, string> parameters) { StringBuilder sb = new StringBuilder(baseURL); if (parameters != null && parameters.Count > 0) { sb.Append("?"); foreach (var pair in parameters) { sb.Append(WWW.EscapeURL(pair.Key)).Append("=").Append(WWW.EscapeURL(pair.Value)).Append("&"); } sb.Remove(sb.Length - 1, 1); } return sb.ToString(); }
こちらを参考にさせて頂きました。ありがとうございます。 TwitterAPIを利用するためのアセット"Let's Tweet in Unity!"で検索APIを使うための拡張 · GitHub
これでurlとparameterを渡せばGETリクエスト用のURLとしてビルドしてくれる関数が出来上がりました。
これを上手に使ってGetUserTimelineを完成させましょう。
public static IEnumerator GetUserTimeline(string user_id, string consumerKey, string consumerSecret, AccessTokenResponse response, GetUserTimelineCallback callback) { // Need to fill body since Unity doesn't like an empty request body. byte[] dummmy = null; string url = GetUserTimelineURL; Dictionary<string, string> parameters = new Dictionary<string, string>(); parameters.Add("user_id", user_id); parameters.Add("count", 30.ToString()); parameters.Add("include_rts", "false"); url = BuildURL (url, parameters); // HTTP header Dictionary<string, string> headers = new Dictionary<string, string>(); headers["Authorization"] = GetHeaderWithAccessToken("GET", url, consumerKey, consumerSecret, response, parameters); WWW web = new WWW(url, dummmy, headers); yield return web; if (!string.IsNullOrEmpty(web.error)) { Debug.Log(string.Format("GetUserTimeline - failed. {0}\n{1}", web.error, web.text)); callback(false, web.error); } else { string error = Regex.Match(web.text, @"<error>([^&]+)</error>").Groups[1].Value; if (!string.IsNullOrEmpty(error)) { Debug.Log(string.Format("GetUserTimeline - failed. {0}", error)); callback(false, web.error); } else { callback(true, web.text); } } }
これで、引数user_id
で与えられたUserのツイートを30件(RTは含まない)取得する、というコードになりました。
parameters
にリクエストのパラメーターを与えます。今はサンプルなのでここで定義していますが、外側から設定できるようにもう一つ引数を設けてもいいかもしれないですね。
Twitter.cs
側の記述は以上です。
最後に呼び出す側のコードを記述して終わりにしましょう。
呼び出し方は
StartCoroutine(Twitter.API.GetUserTimeline(m_AccessTokenResponse.UserId, CONSUMER_KEY, CONSUMER_SECRET, m_AccessTokenResponse, new Twitter.GetUserTimelineCallback(this.OnGetUserTimeline)));
です。コールバック関数は
void OnGetUserTimeline(bool success, string response) { print ("GetUserTimeline- " + (success ? "succedded." : "failed.")); if (success) { var json = JSON.Parse (response); } }
のようにすると良いでしょう。
これでGetUserTimeline ()
の実装は完了しました。
その他のGETリクエストを叩く関数を作成する際はGetUserTimeline ()
を、POSTリクエストの際はPostTweet ()
を参考にするといいでしょう。
Twitterの実装はこんな感じですね。ライブラリがファイルが一つで完結していて軽量かつ改良の加えやすいものになっています。
かなり扱いやすいライブラリだといえるのではないでしょうか。これを参考にしてUnityでTwitterクライアントを作ってみてください!
UnityでFacebook
続いて、UnityでFacebookAPIを叩いてみましょう。こちらは導入が面倒ですが、APIを叩くための関数をライブラリが用意していてくれたりと、親切な設計になっています。(そもそものFacebookAPIがクソだという説もありますが)
インポート
まずはインポートから進めていきましょう。今回は以下のAssetを使用します。
雑に「Unity Facebook」でググると、何故かバージョンの低いものがサジェストされ、コードの闇に飲まれる事になるので気をつけましょう。
上のAssetをインポートしてください。インポート後、一度Unityを再起動して下さい。
Facebookアプリケーションの作成
続いて、APIをテストするためにTwitter同様、Facebookアプリケーションを作成してください。
Facebook APIを使って、コマンドラインから JSON形式のデータを取得してみる
こちらを参考にするといいでしょう。App Name
とApp Id
を使うので、記述されているページを表示しておいてください。
初期設定
作成が完了したら、上のメニューバーからFacebook -> Edit Settings
に行き、先ほど作成したアプリのApp Name
とApp Id
を設定してあげてください。
テストシーンの作成
続いて、作業用のテストシーンを作成しましょう。
Twitterと似たような作業なので、細かい説明は省きます。
こんな感じになりました。それぞれの説明をします。
ReadLoginButton (Button)
ReadPermissionでログインするためのButton
PublishLoginButton (Button)
PublishPermissionでログインするためのButton
InputPostField (InputField)
Postを入力するInputField
PostButton (Button)
Post用のButton
FacebookComponent (GameObject)
FacebookComponentHandler.cs
を当てた、空のGameObject
です。
コードの記述
それではコードを書いていきましょう。FacebookComponentHandler.cs
を開いてください。
using ディレクティブ
例のごとく、using ディレクティブを記述していきましょう。
using UnityEngine; using UnityEngine.UI; using System.Collections; using System.Collections.Generic; using System.Linq; using Facebook.Unity;
です。
変数定義
続いて変数を定義していきます。以下のように記述してください。
public class FacebookComponentHandler : MonoBehaviour { public GameObject inputPostField; private string status = ""; private string lastResponse = "";
やや強引ですが、Example/MainMenuのコードをお借りするために、status
とlastResponse
を定義しました。
Init処理
このライブラリでは、あらゆる処理をする前に、まずFB.Init()
を実行するよう定められています。
Start ()
に記述しましょう。
// Use this for initialization void Start () { FB.Init (OnInitComplete, OnHideUnity); }
です。諸々のコールバックイベントは後ほど定義します。
OnClickEventの定義
続いて、OnClickEventの定義をしていきましょう。
public void OnClickReadLoginButton () { FB.LogInWithReadPermissions(new List<string>() { "public_profile", "email", "user_friends", "user_posts" }, this.HandleResult); } public void OnClickPublishLoginButton () { FB.LogInWithPublishPermissions(new List<string>() { "publish_actions", "user_posts" }, this.HandleResult); } public void OnClickPostButton () { FB.API ("me/posts", HttpMethod.GET, this.HandleResult); }
こんな感じです。
Loginには二種類の関数が用意されております。ReadPermissionのScopeを認証させるためにはFB.LogInWithReadPermissions ()
、PublishPermissionのScopeを認証させるためにはFB.LogInWithPublishPermissions ()
を使います。
それぞれ、一つ目の引数にstringの引数を渡すことでscopeを設定しています。
Postの方はFB.API ()
という関数を使っています。他のAPIを使う際もほぼこの関数のお世話になることでしょう。
第一引数に叩くAPI、第二引数にリクエストの種類を渡します。
これでOnClickEventの定義は完了です。
コールバック関数の定義
続いて、コールバック関数の定義をしていきましょう。
以下のように記述します。
private void OnInitComplete() { status = "Success - Check log for details"; lastResponse = "Success Response: OnInitComplete Called\n"; string logMessage = string.Format( "OnInitCompleteCalled IsLoggedIn='{0}' IsInitialized='{1}'", FB.IsLoggedIn, FB.IsInitialized); print ("status = " + status); print ("lastResponse = " + lastResponse); print (logMessage); } private void OnHideUnity(bool isGameShown) { status = "Success - Check log for details"; lastResponse = string.Format("Success Response: OnHideUnity Called {0}\n", isGameShown); print ("status = " + status); print ("lastResponse = " + lastResponse); print("Is game shown: " + isGameShown); } void HandleResult(IResult result) { if (result == null) { lastResponse = "Null Response\n"; print (this.lastResponse); return; } // Some platforms return the empty string instead of null. if (!string.IsNullOrEmpty(result.Error)) { status = "Error - Check log for details"; lastResponse = "Error Response:\n" + result.Error; print (result.Error); } else if (result.Cancelled) { status = "Cancelled - Check log for details"; lastResponse = "Cancelled Response:\n" + result.RawResult; print (result.RawResult); } else if (!string.IsNullOrEmpty(result.RawResult)) { status = "Success - Check log for details"; lastResponse = "Success Response:\n" + result.RawResult; print (result.RawResult); } else { lastResponse = "Empty Response\n"; print (this.lastResponse); } }
このように記述します。APIの結果はHandleResult ()
をコールバックに渡せば大体の事は分かります。
これでコードの方は完成です。
エディタ上での設定
最後に、エディタ上での設定をしましょう。
publicなGameObject型変数の値を設定
publicなGameObjectとして宣言した変数に値を設定していきましょう。
これでOKです。
OnClickEventの設定
続いて、OnClickEventを設定していきます。これもTwitterの方で行った手順とほぼ同じなので詳細は割愛させていただきます。
設定先は
ReadLoginButton
にOnClickReadLoginButton ()
PublishLoginButton
にOnClickPublishLoginButton ()
PostButton
にOnClickPostButton ()
です。
完成
これで完成です!
使い方は、ReadLoginをクリックし、出てきたFindAccessTokenをクリック、出てきたUserTokenをコピーし、UnityのUserToken欄にペーストし、SendSuccessをクリックします。
同じことをPublishLoginのボタンでもやりましょう。
両方完了したら、InputPostFieldに適当な文章を打ち込み、PostButtonをクリックしてみてください。無事成功していれば、あなたのタイムラインにPostが表示されているはずです。
これでFacebookの実装は完了ですね。折角なのでFacebookでも他のAPIを叩いてみる、という事をしてみましょう。
他のAPIを叩いてみる
今回はGET me/feed
を叩いて、これまでの自分の投稿を取得してみましょう。
必要なscopeは、ReadPermissionsのuser_posts
です。このように、APIによって様々なscopeが求められるので注意しましょう。
実装する前にGraph API エクスプローラーを使うと、必要なscopeが足りているか、などが分かるのでそちらも使ってみると良いでしょう。
それでは実装してみます。
Init完了後でないと不具合が起きるので、InitのcallbackであるOnInitComplete ()
内で呼び出します。
private void OnInitComplete() { status = "Success - Check log for details"; lastResponse = "Success Response: OnInitComplete Called\n"; string logMessage = string.Format( "OnInitCompleteCalled IsLoggedIn='{0}' IsInitialized='{1}'", FB.IsLoggedIn, FB.IsInitialized); print ("status = " + status); print ("lastResponse = " + lastResponse); print (logMessage); if (FB.IsLoggedIn) { var aToken = Facebook.Unity.AccessToken.CurrentAccessToken.Permissions; if (aToken.Contains("user_posts")) { FB.API ("me/feed", HttpMethod.GET, this.OnGetAllPosts); } } }
こんな感じです。万全を期して、既にログインしているかどうかという判定と、認証したscope内にuser_posts
が含まれているかどうか、という判定を取ります。
APIを叩いている処理自体はFB.API ("me/feed", HttpMethod.GET, this.OnGetAllPosts);
です。こんな感じで大体のAPIが叩けるので、このライブラリはいいですね。
コールバックの処理も書いていきます。今回はTwitter同様、responseをまたJSONにパースするという事をしたいので、独自のコールバック関数を設定しました。例のごとく他のusingが書かれている項にusing SimpleJSON
を追記しておいてください。
コールバック関数は以下のように記述します。
void OnGetAllPosts (IResult result) { if (!string.IsNullOrEmpty(result.RawResult)) { var allPostJson = JSON.Parse (result.RawResult); foreach (JSONNode post in allPostJson.Childs) { print (post ["id"]); } } }
result.RawResult
がTwitterの方でいうresponse
です。こいつをパースすればレスポンスのJSONObjectになりますね。
と、こんな感じでFacebookで他のAPIを実装するのは比較的楽です。あっという間でしたね。
これらを参考に、皆さんもUnityでFacebookのクライアントを作ってみてください!
おわりに
相当な長文となりましたが如何だったでしょうか。UnityでこれらのAPIを叩く知見が纏まった記事が見当たらなかったので書いてみました。
実際Unityで作成すると凝ったビジュアルやアニメーションが簡単に実装出来るので、ビジュアル重視のSNSクライアントを作成する選択肢として、Unityはそんなに悪くないんじゃないかなあとか個人的には思います。
皆さんもSNSクライアントを作成する際には、是非Unityを採用してみて下さい!(自己責任でお願いします)
明日は@ymyzkです!お楽しみに!