夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

Hololens用のオリジナルUIを作成する。 ~スイッチレバー その⑤~ イベントの実行の制限とリセット

MRTKを基にHoloLensで使用できるオリジナルのUIを作成します。

過去にSFチックのUIを作成していました。 今回はシリーズ続編としての第三回です。

〇第一弾

redhologerbera.hatenablog.com

〇第二弾

redhologerbera.hatenablog.com

本シリーズで作成したものは以下でMITライセンスで公開しています。(自由に使ってください)

github.com

今回第三弾はレバー(stick)型のUIを作っています。前回まででユーザーがレバーを『握ったことの検知』、『上下左右の動きの検知』、『ユーザーが握ることをやめたら初期位置にリセット』するところまで機能を作りました。

〇入力イベントを最初の一回のみ実行されるようにする。

ここまでで上下左右の動きに応じた入力でイベントが発火しました。

f:id:Holomoto-Sumire:20200610110129g:plain

前回の場合下の画像のようにイベントでオブジェクトのboolをTrueに変更しているのでわかりずらいですが、

f:id:Holomoto-Sumire:20200611094331j:plain

現状だと右を検知している間ずっとイベントが発火し続けてしまっています。

 public void Update()
    {
        ...
            if (result && resulty && resultabsy)
            {
                reslutUpperAxisEvent();
            }
    }
  ...
  void reslutRightAxisEvent()
    {
        OnUpdateRightAxisEvent.Invoke();
        Debug.Log("RightEvent");
    }
...

f:id:Holomoto-Sumire:20200611095035j:plain

これでは何かと不都合です。例えば上下左右の動きを検知してオブジェクトをInstanciateする関数を発火させていたら毎フレームごとにオブジェクトが生成されてしまいます。

ここを次のように変更しました。

 bool _OnUpdaterightAxisEvent = true;//追加
 public void Update()
    {
        ...
            if (result && resulty && resultabsy)
            {
                if (_OnUpdaterightAxisEvent)//条件分岐を追加
                {
                    reslutUpperAxisEvent();
                }
            }
    ...
   }
...
  void reslutRightAxisEvent()
    {
        OnUpdateRightAxisEvent.Invoke();
        _OnUpdaterightAxisEvent = false;
        Debug.Log("RightEvent");
    }

これで _OnUpdateupperAxisEventがtrueの時のみイベントが実行するようにできました。

イベント実行後は_OnUpdateupperAxisEventをfalseに変更し一度のみイベントが実行されるようにしました。

Left,Upper,Downも同様に一度のみイベントが実行されるようにします。

...
    bool _OnUpdateupperAxisEvent = true;
    bool _OnUpdatedownAxisEvent = true;
    bool _OnUpdaterightAxisEvent = true;
    bool _OnUpdateleftAxisEvent = true;
...
    public void Update()
    {
        if (_ActionEnebled)
        {
             ...
            if (!resultabsx && !resultabsy)
            {
                //  UpdateStatus(false, false, false, false);
            }

            if (result && resulty && resultabsy)
            {
                if (_OnUpdateupperAxisEvent)
                {
                    reslutUpperAxisEvent();
                }
            }

            if (result && !resulty && resultabsy)
            {
                if (_OnUpdatedownAxisEvent)
                {
                    reslutDownAxisEvent();
                }
            }

            if (!result && resultx && resultabsx)
            {
                if (_OnUpdaterightAxisEvent)
                {
                    reslutRightAxisEvent();
                }
            }

            if (!result && !resultx && resultabsx)
            {
                if (_OnUpdateleftAxisEvent)
                {
                    resultLeftAxisEvent();
                }
            }
        }
    }

これで最初の一回だけイベントが実行されるようになりました。

f:id:Holomoto-Sumire:20200611122409j:plain
RightEventのログは一度のみ

〇リセット時に再びイベントを実行できるようにする

 これでイベントが一度のみ実行されますが、どこかでリセットを行わない限りシーン実行中(アプリ起動時)一度のみしかイベントを起こせなくなります。 一度入力するとそれ以降反応しなくなるレバーはUIとしてはそれは問題なのでリセットできるようにします。

レバーを握るのをやめたとき走るleverHoldEnd関数に追記します。

    public void leverHoldEnd()
    {
        Debug.Log("leverActionEnd");
        _ActionEnebled = false;
        Debug.Log("PointerReset");
        this.gameObject.transform.localPosition = new Vector3(0, 0, 0);
        _OnUpdateupperAxisEvent = true;//追加
        _OnUpdatedownAxisEvent = true;//追加
        _OnUpdaterightAxisEvent = true;//追加
        _OnUpdateleftAxisEvent = true;//追加
    }

これでターゲットを握ることをやめたときに_OnUpdateupperAxisEventが再びTrueになり再度イベントが走るようになりました。

ここまで機能を『動かすことベース』に作ってきたので次回は変数名などを見やすく変更します。