@Baiteen
ReactiveExtensionsがUnityでも使えるってのを今更知ったので、今更ながら使ってみた。その5。
やりたいこと
ReactiveExtensionsを使ってREST APIにスコアをPOSTする。サーバー立ててAPI用意するのは面倒くさいので、アカウントがあるParse.comで試してみることにする。
やったこと
(UniRxはインポート済み)1.
Parse.comにログインしてアプリ作ってスコア保存用のクラスを用意。(playerとscoreフィールドも追加)
詳しい方法は割愛。(元気が足りず諦めました)
2.
Parse.comのREST APIの仕様を確認。(見るだけ)
まずはRequestFormatを確認。ここ。
なるほど。
Content-Typeをapplication/jsonにして、X-Parse-Application-IdとX-Parse-REST-API-Keyを指定すればいいのね。
IdとKeyはアプリケーションの設定画面にありました。
それからデータの登録方法を確認。ここ。
なるほど。
URLで登録するクラス指定して、ポストデータで登録したいデータをjsonで渡せばいいのね。
3.
MiniJSONを使えるようにする。
JSONデータを渡すということなので、オブジェクトをJSON文字列にしてくれるMiniJSONを使うことにしました。
https://gist.github.com/darktable/1411710からMiniJSON.csをダウンロード。
UnityのAssetsフォルダ内にPluginsフォルダを作ってそこにドラッグドロップ。
これで使えるようになったはず。
4.
Unityでスクリプト書いてみる。
スコア登録用のScoringクラスを用意して、マウスダウンで登録実行するのをイメージ。
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UniRx; using MiniJSON; public class TestScript : ObservableMonoBehaviour { ///ん?何やらエラー発生してる。スコアを登録してくれるクラス public class Scoring { ///プレイヤー名 private string Player { get; set; } ///REST APIのURL private string ApiUrl { get { return "https://api.parse.com/1/classes/Ranking"; } } ///リクエストに必要なheader private Hashtable Headers { get { var headers = new Hashtable (); headers ["X-Parse-Application-Id"] = "******";//自分のアプリのIDを入れてね headers ["X-Parse-REST-API-Key"] = "******";//自分のアプリのKeyを入れてね headers ["Content-Type"] = "application/json"; return headers; } } ///コンストラクタでプレイヤー名設定 public Scoring (string player) { this.Player = player; } ///スコア登録Observable(3回リトライしてみる)レスポンス文字列をそのまま発行 public IObservablePushScore (int score) { var form = new WWWForm(); form.AddField("player", this.Player); form.AddField("score", score); return ObservableWWW.Post(this.ApiUrl, form, this.Headers).Retry(3); } } /// RXのサンプルがAwakeだったので、ここに書きました。 public override void Awake () { //参考サイト:http://neue.cc/2010/07/28_269.html //マウスダウンでスコア登録 OnMouseDownAsObservable() .SelectMany(_ => new Scoring("baiteen").PushScore(100)) .Subscribe (result => { Debug.Log ("finish"); }); // If you use ObservableMonoBehaviour, must call base method ← サンプルにこう書いてますので、そのまま。 base.Awake (); } }
ArgumentException: Key duplication when adding: Content-Type
調べてみると"application/x-www-form-urlencoded"か"multipart/form-data"が最初から設定されてるらしい。
消そうと思ったけど消せない。
もうちょっと調べてみたら
WWWクラスでは、WWWFormじゃなくてbyte[]でポストデータを指定できるみたい。
なぜObservableWWW.Postにはbyte[]が渡せないんだー!!
ってことでbyte[]渡せるようにオーバーロード追加してやってみた。
■追加したコード(UniRx/Scripts/UnityEngineBridge/ObservableWWW.cs)
public static IObservablePost(string url, byte[] content, Hash headers, IProgress progress = null) { return Observable.FromCoroutine ((observer, cancellation) => FetchText(new WWW(url, content, headers), observer, progress, cancellation)); }
んで、スクリプトのPushScoreを以下に修正(bloggerに貼るとobjectがobject=""になっちゃう)
///お、今度はエラー出ない。スコア登録Observable(3回リトライしてみる)レスポンス文字列をそのまま発行 public IObservablePushScore (int score) { var dic = new Dictionary (); dic.Add ("player", this.Player); dic.Add ("score", score); byte[] data = System.Text.Encoding.UTF8.GetBytes (Json.Serialize (dic)); return ObservableWWW.Post(this.ApiUrl, data, this.Headers).Retry(3); }
5.
Parse.comのDataBrowserで確認。
すばらしい。ちゃんとデータ登録されてる。
例外処理とかは置いといて、とりあえずUniRxでPOSTできることが確認できたので良かった。
良かった。