Unity UniRxをつかってスワイプでカメラ移動をしてみた

raharu(仮名)(プログラマー)
これがダイバージェンス1%の先の世界か。。。

UniRxをAssetsストアから落としてきます。

アセット検索すれば出てきます。

パネルを用意する

f:id:raharu0425:20150716182503p:plain

今回わかりやすいように色をかえてみましたが
特に意味はありません。

カメラの位置を決定する

f:id:raharu0425:20150716182327p:plain

斜め45℃下を向くカメラを置き、パネル全体が写るように調整します。

カメラにRigidBodyを追加する。
f:id:raharu0425:20150716183902p:plain

適当なオブジェクトに下記スクリプトをアタッチする

名前は適当にCameraMove.csにしました。
MainCameraにカメラをタッチします。

f:id:raharu0425:20150716184053p:plain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using UnityEngine;
using System.Collections;
using System;
using UniRx;

public class CameraMove : MonoBehaviour {

    //メインカメラ
    public Camera MainCamera;

    // Update
    void Update () {
        // マウスが押された場合
        if (Input.GetMouseButtonUp(0)) {
        } else if (Input.GetMouseButton(0)) {
            MapSwipe();
        }
    }


    //スワイプの処理
    public void MapSwipe()
    {
        //mousePositionの取得
        var drug = Observable.EveryUpdate ().Select (pos => Input.mousePosition);
        //クリックが話されたら購読停止
        var stop = Observable.EveryUpdate ().Where(_ => Input.GetMouseButtonUp(0));

        //マウスポジションの4フレーム後のポジションを比較してカメラのRigidbodyに力を加える。
        IDisposable onDrug = drug.Zip (drug.Skip (4), (pos1, pos2) => new {x = pos2.x - pos1.x, z = pos2.y - pos1.y})
            //クリックが話されたら購読停止
            .TakeUntil(stop)
            .Subscribe (deltaPosition => {
                MainCamera.gameObject.GetComponent<Rigidbody>().velocity = new Vector3(deltaPosition.x, 0, deltaPosition.z) *  -5;
            }
        );
    }


}


スワイプ- YouTube

いい感じにうごきました、がブログ用に抜粋して書いたのでちょっといびつですね。
実際はupdate内で状態管理したりすると思います。

稼働領域の限界値はSubscribe内に書くと慣性の力で限界値よりも動いてしまう場合があるので
それはupdate内で監視しておいた方がいいかもしれません。

また、購読完了はTakeUntilでやりましたが、実際に使う場合は
停止は停止でSubscribe呼び出してその中でステート変更などを行うのが良いでしょう。

次は似非ピンチイン、ピンチアウトでも作成しようかと思います。

— 追記

上記スクリプトはエディター専用で実機の場合は別途対応が必要になります。
面倒くさがらずにあるなら書けやと言われそうなので下記に記載しておきます。
参考までにどうぞmm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using UnityEngine;
using System.Collections;
using System;
using UniRx;

public class CameraMove : MonoBehaviour {

    //メインカメラ
    public Camera MainCamera;

    // Update
    void Update () {

       #if UNITY_EDITOR
        // マウスが押された場合
        if (Input.GetMouseButtonUp(0)) {
        } else if (Input.GetMouseButton(0)) {
            MapSwipe();
        }
       #elif UNITY_IOS || UNITY_ANDROID

        if (Input.touchCount == 0) {
        } else if (Input.touchCount == 1) {
            MapSwipe();
        }
       #endif
    }


    //スワイプの処理
    public void MapSwipe()
    {
       #if UNITY_EDITOR
        //mousePositionの取得
        var drug = Observable.EveryUpdate ().Select (pos => Input.mousePosition);
        //クリックが話されたら購読停止
        var stop = Observable.EveryUpdate ().Where(_ => Input.GetMouseButtonUp(0));
       #elif UNITY_IOS || UNITY_ANDROID
        //positionの取得
        var drug = Observable.EveryUpdate ().Select (pos => Input.GetTouch(0).position);
        //タッチカウントが変更され場合に購読停止
        var stop = Observable.EveryUpdate ().Where(_ => Input.touchCount != 1);
       #endif

        //マウスポジションの4フレーム後のポジションを比較してカメラのRigidbodyに力を加える。
        IDisposable onDrug = drug.Zip (drug.Skip (4), (pos1, pos2) => new {x = pos2.x - pos1.x, z = pos2.y - pos1.y})
            //クリックが離されたたら購読停止
            .TakeUntil(stop)
            .Subscribe (deltaPosition => {
                MainCamera.gameObject.GetComponent<Rigidbody>().velocity = new Vector3(deltaPosition.x, 0, deltaPosition.z) *  -5;
            }
        );
    }
}

ご意見マサカリ等歓迎しております!