Viveの入力をActionで扱い、コードを綺麗にする話

#はじめに
HTC Viveは様々な入力方法があるし、Unityでは扱いやすいのでいろいろ想像が膨らんで楽しいですね！

ただ普通にコード書くと例えば以下のようなコードを書きがちです。


```csharp:tmp.cs
    void Update()
    {
        SteamVR_TrackedObject trackedObject = con.GetComponent<SteamVR_TrackedObject>();

        var device = SteamVR_Controller.Input((int)trackedObject.index);

        if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger))
        {
                //Viveでトリガーを押した時に何か処理をする
        }
    }

```

流石にtrackedObjectはStart()で宣言するだけに留めるにしても、
その宣言や`if(device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger))`なんてことはいちいちクラス毎に書いてられません。

なので、今回はViveの入力をEventで扱うクラスを作って各クラスでそれを利用しましょうという話です。


#入力をEventで扱うクラス書く

今回は左コントローラのEventHandlerを書きましょう

```LeftViveControllerHandler.cs
using UnityEngine;
using System.Collections;
using System;
public class LeftViveControllerHandler : MonoBehaviour
{
    public SteamVR_TrackedObject trackedObject { get; set; }
    public SteamVR_Controller.Device device { get; set; }

    public static Action GripButton_Pressed();
    public static Action Trigger_SharrowPressed();
    public static Action Trigger_DeepPressed();
    public static Action Trigger_Released();
    public static Action TouchPad_Pressed();
    public static Action TouchPad_Pressing();
    public static Action TouchPad_Released();
    public static Action TouchPad_TouchDown();
    public static Action TouchPad_Touching();
    public static Action TouchPad_TouchUp();
    public static Action MenuButton_Pressed();

    void Start()
    {
        trackedObject = GetComponent<SteamVR_TrackedObject>();
        device = SteamVR_Controller.Input((int)trackedObject.index);
    }
    void Update()
    {
        if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger))
        {
            Trigger_SharrowPressed();
        }
        if (device.GetPressDown(SteamVR_Controller.ButtonMask.Trigger))
        {
            Trigger_DeepPressed();
        }
        if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Trigger))
        {
            Trigger_Released();
        }
        if (device.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad))
        {
            TouchPad_Pressed();
        }
        if (device.GetPress(SteamVR_Controller.ButtonMask.Touchpad))
        {
            TouchPad_Touching();
        }
        if (device.GetPressUp(SteamVR_Controller.ButtonMask.Touchpad))
        {
            TouchPad_Released();
        }
        if (device.GetTouch(SteamVR_Controller.ButtonMask.Touchpad))
        {
            TouchPad_Touching();
        }
        if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Touchpad))
        {
            TouchPad_TouchDown();
        }
        if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Touchpad))
        {
            TouchPad_TouchUp();
        }
        if (device.GetPressDown(SteamVR_Controller.ButtonMask.ApplicationMenu))
        {
            MenuButton_Pressed();
        }
        if (device.GetPressDown(SteamVR_Controller.ButtonMask.Grip))
        {
            GripButton_Pressed();
        }
    }
}

```

Viveで何かしら入力を行うとそれに対応したEventメソッドが発火するようになっています。

#利用する

```MenuManager.cs
using UnityEngine;
using System.Collections;

public class MenuManager : MonoBehaviour
{
    void Start()
    {
        LeftViveControllerHandler.GripButton_Pressed += DoSomethingOnGripButton_Pressed;
    }

    void DoSomethingOnGripButton_Pressed() {
        //グリップボタンが押されたときの処理を書く
    }

}
```

例えばこのコードなら、ViveのGripButtonをクリックした時の処理をStart()で登録しています。
その処理では、子要素をEnableにしたりDisableにしたりします。
普通にやると最初に書いたようにUpdate()作ってそこにif文を書くと思うのですが、それに比べれば軽量でスリムなコードが書けると思います。



今回はたまたまViveの話でしたが、例えばInput.KeyDownとかもEventとして扱いたい時は同様に入力を扱うクラスを作れば良いので、割と使いまわせる概念だと思います。以上です。