Unity3DとuGUIとUniRxのコラボでサーバ連携への第一歩

コルーチンってうざったいです

本日はサーバのAPIにアクセスして結果を取得して表示するまでの流れを uGUI と UniRx を使ってやってみます。

新規プロジェクト作成

ss20150206_0143

File → New Project… で新規プロジェクトを作成します。

ss20150206_0146

(1) プロジェクトフォルダは各自環境に合わせて適宜指定してください。

(2) Create をクリックでプロジェクト作成完了です。

UI作成

ss20150206_0157

ss20150206_0159

Hierarchy ビューにて、Panel を生成します。右クリックは Hierarchy ビューの中の何もないところでやります。

ss20150206_0203

ss20150206_0207

ss20150206_0215

Hierarchy ビュー Panel を右クリックし、UI → InputField の順でクリックし、入力フィールドを生成します。
Panel 生成後は Scene ビューにて、いい感じの場所にとりあえずうつしておきましょう。
最後に Hierarchy ビューの InputField をクリックし、txtPar1 という名前に変えておきます。

ss20150206_0219

ss20150206_0222

ss20150206_0225

同じ要領でもうひとつ、InputField を作成し、いい感じの場所に移動し、名前を txtPar2 にしておきます。
移動するとき、近くの UI との位置あわせがしやすいように、スナップしてくれます。結構便利。
名前も txtPar2 としておきます。

ss20150206_0229

ss20150206_0231

ss20150206_0232

次は、Button を追加します。
いい感じに移動させて、名前を btnSubmit とでもしておきます。

ss20150206_0235

ss20150206_0241

ss20150206_0243

最後の UI です。Text を追加して、移動して、txtResult とします。
ちなみに、移動させるのはテキスト表示エリアの左上の丸いハンドルのみ動かして、表示範囲を大きくする感じです。
書き忘れてましたが、2D モードにしておきましょう。

これで、UI 完成です。

UniRx – Reactive Extensions for Unity のインストール

neuecc さんによって公開されている UniRx と、LINQ to GameObject をインストールしましょう。
これがあるとプログラムがものすごく楽になります。

ss20150206_0247

Window → Asset Store をクリックして、アセットストアウインドウを開きます。

ss20150206_0249

ss20150206_0251

検索窓に UniRx と打ち込んで、UniRx – Reactive Extensions for Unity ページを開きます。

ss20150206_0253

ss20150206_0255

アセットの詳細ページを開いたら、「ダウンロード」「インポート」のボタンをクリックし、インポートを実行します。

LINQ to GameObject のインストール

ss20150206_0258

ss20150206_0300

ss20150206_0301

ss20150206_0302

検索窓に Linq と打ち込んで、LINQ to GameObject を検索し、詳細ページを開きます。
先ほどと同様にダウンロードしてインポートしてください。

これで、準備 OK です。

PHPサーバーAPIもどきを準備

<?php

$par1 = isset($_REQUEST['par1']) ? (int)$_REQUEST['par1'] : false;
$par2 = isset($_REQUEST['par2']) ? (int)$_REQUEST['par2'] : false;

$aoResult = array();

try {

  if (!$par1) { throw new Exception('Error in par1'); }
  if (!$par2) { throw new Exception('Error in par2'); }

  $aoResult['code'] = 'ok';
  $aoResult['result'] = $par1 + $par2;


} catch (Exception $ex) {

  $aoResult['code'] = 'error';
  $aoResult['error'] = $ex->getMessage();

}

echo json_encode($aoResult);

Unity からコールするためのスクリプトをとりあえず用意しておきます。

スクリプトを生成する

ss20150206_0314

ss20150206_0317

Project ビューにて Create → C# Script をクリックし、ServerCall スクリプトを生成します。
そして、Project ビューの ServerCall を Hierarchy ビューの Panel にドロップして関連付けしておきます。

ServerCall.csをコーディング

using UnityEngine;
using UnityEngine.UI;           // InputField や Text などの UI で必要
using UnityEngine.EventSystems; // uGUI のクリックイベントの処理で必要
using Unity.Linq;               // Linq で gameObject にアクセスする
using System.Collections;
using System.Linq; // iOS で使うと動かない可能性あり
using UniRx;       // クリックイベントを Observable に変換する

public class ServerCall : ObservableMonoBehaviour {

    void Start() {

        // 入力フィールド1のコンポーネントを取得
        InputField txtPar1 = null;
        gameObject.Descendants()                       // Panel の子供を列挙する
            .Where(x => x.name == "txtPar1")           // txtPar1 の名前だけ抽出
            .Select(x => x.GetComponent<InputField>()) // InputField コンポーネントを取得
            .Where(x => x != null)                     // InputField コンポーネント取得結果、null でなければ続ける
            .ToObservable()                            // InputField コンポーネントを通知する
            .Subscribe(x => txtPar1 = x);              // 受け取った InputField コンポーネント通知を txtPar1 に格納する

        // 入力フィールド2のコンポーネントを取得
        InputField txtPar2 = null;
        gameObject.Descendants()
            .Where(x => x.name == "txtPar2")
            .Select(x => x.GetComponent<InputField>())
            .Where(x => x != null)
            .ToObservable()
            .Subscribe(x => txtPar2 = x);

        // テキストフィールドコンポーネントを取得
        Text txtResult = null;
        gameObject.Descendants()
            .Where(x => x.name == "txtResult")
            .Select(x => x.GetComponent<Text>())
            .Where(x => x != null)
            .ToObservable()
            .Subscribe(x => txtResult = x);

        // 上記コンポーネントが全部取れてるのが条件
        if (txtPar1 != null && txtPar2 != null && txtResult != null) {
            // クリックイベントを Observable に変換(つまり、クリックする度にメソッドチェインに値が流れていく)
            OnTriggerEventAsObservable()
                .Where(x => x.selectedObject.name == "btnSubmit") // 通知元の gameObject 名が "btnSubmit" が条件
                .Subscribe(x => txtResult.text = "Click " + System.DateTime.Now.ToString()); // 結果を表示
        }
    }

    Subject<BaseEventData> onTriggerEvent; // ボタンクリック Subject (通知する側)

    // クリックされると呼ばれるメソッド
    public void OnTriggerEvent(BaseEventData ev) {
        if (onTriggerEvent != null) onTriggerEvent.OnNext(ev); // オブザーバに通知するだけ
    }

    // Start メソッドで使用する、クリックイベントを Observable に変換するメソッド
    public IObservable<BaseEventData> OnTriggerEventAsObservable() {
        return onTriggerEvent ?? (onTriggerEvent = new Subject<BaseEventData>());
    }

}

なんで、OnTriggerEvent の中で直接処理しないの?
なんで、Button のイベントでやらないで、EventTrigger なの?

とかいう疑問は次回のウェブアクセスで多分解消されるかもしれません。

イベントトリガーをUIに設定する

ss20150206_0346

ss20150206_0349

Hierarchy ビューの btnSubmit をクリックして選択状態にします。
Inspector ビューの Add Component → Event → Event Trigger をクリックして、Event Trigger コンポーネントを追加します。

ss20150206_0402

(1) btnSubmit の Inspector ビューの Add New Event Type → PointerClick をクリックしてイベントを追加

(2) + をクリックしてリストイベントのリストを追加

(3) Hierarchy ビューの Panel を 上記で追加したリストの gameObject にドロップして関連付け

(4) No Function → ServerCall → OnTriggerEvent の順にクリックし、実行するメソッドを選択

以上で、ボタンクリックでイベント処理に関連付け完了です。

実行してみる

ちょっと時間がかかったので、サーバーへのアクセスはまた次回にいたします。

ではまたー。

ツイートツイート