Oculus Goで物をつかむ

#はじめに
Oculus Goで物をつかんでみたくてサンプルを探したがなかなか見つからない。
Touch用のサンプルはいくつか見つけたので、ちょっと編集してOculus Goで使えるようにするためのメモです。
試してませんがGearVRでも使えると思います。

Demoはこちら。
[https://www.youtube.com/watch?v=SR686aPVT1Q](https://www.youtube.com/watch?v=SR686aPVT1Q)
![vrgrab.gif](https://qiita-image-store.s3.amazonaws.com/0/216837/3292d401-b920-3404-7186-402f2d8dd5d6.gif)

#Vr Grabber
[@hecomi](https://twitter.com/hecomi)さんが公開している[Vr Grabber](https://github.com/hecomi/VrGrabber)がめちゃくちゃクールだったのでこれを編集します。

編集するといってもOVRInputの部分をちょっと変えるだけです。
TouchとGoでは結構違います。詳しくは公式から。
[https://developer.oculus.com/documentation/unity/latest/concepts/unity-ovrinput/#unity-ovrinput-go-controller](https://developer.oculus.com/documentation/unity/latest/concepts/unity-ovrinput/#unity-ovrinput-go-controller)

```c#:VrgOculusTouchDevice.cs
...
public class VrgOculusTouchDevice : IDevice
{
    private OVRInput.Controller GetOVRController(ControllerSide side)
    {
        return (side == ControllerSide.Left) ?
            OVRInput.Controller.LTouch :
            OVRInput.Controller.RTouch;
    }

    public Vector3 GetLocalPosition(ControllerSide side)
    {
        return OVRInput.GetLocalControllerPosition(GetOVRController(side));
    }

    public Quaternion GetLocalRotation(ControllerSide side)
    {
        return OVRInput.GetLocalControllerRotation(GetOVRController(side));
    }

    public bool GetHold(ControllerSide side)
    {
        return OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger);
    }

    public bool GetRelease(ControllerSide side)
    {
        return OVRInput.GetUp(OVRInput.Button.PrimaryIndexTrigger);
    }

    public bool GetHover(ControllerSide side)
    {
        return OVRInput.GetUp(OVRInput.Button.PrimaryIndexTrigger);
    }

    public bool GetClick(ControllerSide side)
    {
        return OVRInput.Get(OVRInput.Button.PrimaryTouchpad);
    }

    public Vector2 GetCoord(ControllerSide side)
    {
        return OVRInput.Get(OVRInput.Axis2D.PrimaryTouchpad);
    }
}
...
```

GetReleaseを追加しています。
Goのコントローラーはtouchpad以外はON/OFFのスイッチのみとなるので、それに合わせてコードを編集しました。

```c#:VrgDevice.cs
...
        public Vector3 GetLocalPosition(ControllerSide side) {
            return _instance.GetLocalPosition(side);
        }

        public Quaternion GetLocalRotation(ControllerSide side) {
            return _instance.GetLocalRotation(side);
        }

        public bool GetHold(ControllerSide side) {
            return _instance.GetHold(side);
        }

        public bool GetRelease(ControllerSide side)
        {
            return _instance.GetRelease(side);
        }

        public bool GetHover(ControllerSide side) {
            return _instance.GetHover(side);
        }

        public bool GetClick(ControllerSide side) {
            return _instance.GetClick(side);
        }

        public Vector2 GetCoord(ControllerSide side) {
            return _instance.GetCoord(side);
        }
...
```

```c#:VrgIDevice.cs
...
public interface IDevice
{
    Vector3 GetLocalPosition(ControllerSide side);
    Quaternion GetLocalRotation(ControllerSide side);
    bool GetHold(ControllerSide side);
    bool GetRelease(ControllerSide side);
    bool GetHover(ControllerSide side);
    bool GetClick(ControllerSide side);
    Vector2 GetCoord(ControllerSide side);
}
...
```

```c#:VrgGrabber.cs
...
    RaycastHit targetHit_;
    bool holdInput_ = false;
    bool releaseInput_ = false;
    bool isHoldStart_ = false;
    bool isHoleEnd_ = false;
    Vector3 preRayDirection_;
...

void UpdateInput()
    {
        var preHoldInput = holdInput_;
        holdInput_ = Device.instance.GetHold(side);
        releaseInput_ = Device.instance.GetRelease(side);
        isHoldStart_ = holdInput_ == true;
        isHoleEnd_ = releaseInput_ == true;
        //isHoldStart_ = (holdInput_ >= grabBeginThreshold) && (preHoldInput < grabBeginThreshold);
        //isHoleEnd_ = (holdInput_ <= grabEndThreshold) && (preHoldInput > grabEndThreshold);
    }
...
```
物体にRayが当たった状態でTriggerを押すとで掴んで、Triggerを離すと掴んでるものを離します。
掴んでいる状態でtouch padに触れると近づけたり遠ざけたりできます。コントローラーは一つしかないのでスケールの変更などはできません。

#Unityパッケージ
こちらからUnityパッケージをダウンロードできます。
[https://github.com/RyoKosaka/VrGrabberGo](https://github.com/RyoKosaka/VrGrabberGo)

インストール方法は[本家のVrGrabber](http://tips.hecomi.com/entry/2017/07/30/234658)と全く同じです。