【Unity(C#)】MirageSoloのシースルーモード導入

##See-Through 
MirageSoloでMRが可能になる新しい機能です。

本記事投稿時点ではベータ版として公開されています。
![MirageSoloMR_min.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/dfac9b93-03a9-f383-bb35-f317132f6c55.gif)


##導入方法
[GoogleVR](https://github.com/googlevr/gvr-unity-sdk/releases)からダウンロードできます。

MirageSoloを用いてビルドを行うまでの手順はこちらの記事が参考になりました。
→[Mirage Soloから始めるDaydream開発](https://qiita.com//JackMasaki/items/a322fd29e4034431d032)

ただし、
・SDK、NDK等のバージョンチェックが必要(動作しないバージョンがある)
・2019.1では動作しない？(ビルドできない、apkファイルを開けない)

などの条件があるのでシースルーモードを導入するにはひと手間必要です。


①Unity2019.1のインストール時にAndroidのもろもろ一緒にダウンロードする
②Unity2018で①でダウンロードしてきたAndroidのもろもろを利用してビルドする

という手順で行えばSDK関連は何も考えず勝手にビルド環境が構築されるのでおススメです。
→さらに詳しくは[こちら](http://bibinbaleo.hatenablog.com/entry/2019/04/17/064702)

あとはMirageSolo側でバージョンアップをして、
`設定`>`ベータ版の機能`>`Turn on see- through mode`のチェックを入れときましょう。

##Hierarchy

`Assets` > `GoogleVR` > `Beta` > `Demos` > `Scenes` > `HelloMR`
を`Add Open Scenes`してビルドするだけでも可能ですが、せっかくなのでまっさらのシーンから配置してみました。

![MirageSoloSetup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/65e8bef9-6912-80e3-f1b4-b23ef825817c.png)
**Player**というゲームオブジェクトはデモシーンにも存在しており、
**コントローラーとカメラを一緒に移動させる**ために用意されたものと解釈して同様の階層構造を再現してます。

Demo用のPrefabやInstantPreviewなどは必要ないので配置してません。

##Script
あとはコードです。

デモシーンのスクリプトはAppボタンを押すと
`VR空間`→`白黒`→`セピア調`→`以後ループ`
の順に遷移するようになっています。

今回は`VR空間`→`セピア調`→`以後ループ`という実装で書き換えました。

```C#:適当なオブジェクトを作ってアタッチ
using GoogleVR.Beta;
using UnityEngine;

public class ViewModeChange : MonoBehaviour
{

    GvrControllerInputDevice gvrControllerInputDevice;

    [SerializeField]
    GameObject[] hideDuringSeeThrough;

    void Start()
    {
        gvrControllerInputDevice = GvrControllerInput.GetDevice(GvrControllerHand.Dominant);

        bool supported = GvrBetaSettings.IsFeatureSupported(GvrBetaFeature.SeeThrough);
        bool enabled = GvrBetaSettings.IsFeatureEnabled(GvrBetaFeature.SeeThrough);
        if (supported && !enabled)
        {
            GvrBetaFeature[] features = new GvrBetaFeature[] { GvrBetaFeature.SeeThrough };
            GvrBetaSettings.RequestFeatures(features, null);
        }
    }

    void Update()
    {
        if (gvrControllerInputDevice.GetButtonUp(GvrControllerButton.App))
        {
            SeeThroughModes();
        }
    }

    void SeeThroughModes()
    {
        if (!GvrBetaSettings.IsFeatureEnabled(GvrBetaFeature.SeeThrough))
        {
            return;
        }

        GvrBetaSeeThroughCameraMode camMode = GvrBetaHeadset.CameraMode;
        GvrBetaSeeThroughSceneType sceneType = GvrBetaSeeThroughSceneType.Augmented;

        switch (camMode)
        {
            case GvrBetaSeeThroughCameraMode.Disabled:
                camMode = GvrBetaSeeThroughCameraMode.ToneMap;
                break;
            case GvrBetaSeeThroughCameraMode.ToneMap:
                sceneType = GvrBetaSeeThroughSceneType.Virtual;
                camMode = GvrBetaSeeThroughCameraMode.Disabled;
                break;
        }

        GvrBetaHeadset.SetSeeThroughConfig(camMode, sceneType);

        bool seethruEnabled = camMode != GvrBetaSeeThroughCameraMode.Disabled;
        foreach (var go in hideDuringSeeThrough)
        {
            go.SetActive(!seethruEnabled);
        }

    }
}

```


スタート内でシースルーモードに対応しているかどうか確認しています。
なくても動きますが一応。

```C#
void Start()
    {
        bool supported = GvrBetaSettings.IsFeatureSupported(GvrBetaFeature.SeeThrough);
        bool enabled = GvrBetaSettings.IsFeatureEnabled(GvrBetaFeature.SeeThrough);
        if (supported && !enabled)
        {
            GvrBetaFeature[] features = new GvrBetaFeature[] { GvrBetaFeature.SeeThrough };
            GvrBetaSettings.RequestFeatures(features, null);
        }
    }
```

##GameObjectのOn,Off
**シースルーモード⇔通常のVRモード**
この遷移時に不要なゲームオブジェクトを非アクティブに、
必要なゲームオブジェクトをアクティブにしています。

```C#
        bool seethruEnabled = camMode != GvrBetaSeeThroughCameraMode.Disabled;
        foreach (var go in hideDuringSeeThrough)
        {
            go.SetActive(!seethruEnabled);
        }
```

使い道の例としては、デモシーンのようにVR空間内で部屋(オブジェクト)の中にいた場合などが挙げられます。

部屋(オブジェクト)自体を消してあげないとシースルーモード時に
部屋(オブジェクト)が邪魔して周りが見えません。


また、別の例として
コントローラーをシースルーモード時に映しっぱなしにしていると
現実空間のものとゲームオブジェクトの両方が目に入って気持ち悪いです。
なので、消してあげたほうがいいです。

このコードももちろん丸パクリなのですが、アクティブ、非アクティブを含めて
たった5行でキレイに書いてて心から美しいと思いました。

##カメラモード
`GvrBetaHeadset.CameraMode`を参照して
現在のカメラモードに応じて、別のカメラモードに切り替えています。

| カメラモード       |       内容 | 
|:-----------------|------------------:|
| Disabled         |              VR空間|  
| RawImage         |              白黒 |       
|ToneMap           |           セピア調|        

---
2019/05/12 追記

今回はスクリプトでカメラモードを変更しました。
最初から最後までシースルーモードを使用し、変更する必要がない場合は
`GvrBetaHeadSet`のパラメータを変更してあげればOKです。

![GvrBetaHeadSetSetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/043f1579-d097-e28e-3184-983a88942a0b.png)


##GvrBetaSeeThroughSceneType
こいつのパラメーターが2つ用意されていて、
`Augmented`と`Virtual`なのですが違いがさっぱりでした。

ドキュメントには
>These control where the scene is rendered from. Generally in a virtual scene the scene should be rendered from the users' eyes while an augmented scene should be rendered from the camera's position to match the see-through images. 

とありましたが、被ってみても何の違いも感じませんでした。

誰かわかる方いたら教えてください。

##色の変更
カメラのBackgroundを変更してあげれば見える景色の色も変えられます。
![MirageSolo_Camera.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/ee65d7a7-54da-e4b1-bed4-81f86f8527fe.png)


![MirageSoloMR_Green.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/1b7d40d0-1c46-4a9e-bed4-cef8425a1435.gif)

![MirageSoloMR_Blue.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/551c1e2d-9303-7cb2-b2f3-07acaa93ac62.gif)

![MirageSoloMR_Red.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/6b7233e6-63a8-9c44-b039-f576a4288f88.gif)


MirageSolo(Daydream)に幸あれ...