Unity－OculusGo連携。。。VR動画で遊んでみた♬マウスで操作。。出来た！

やはり動かしたいということで、以下の参考の["Query-Chan" model](https://assetstore.unity.com/packages/3d/characters/query-chan-model-20031?aid=1101lIAt&utm_source=aff)をやってみました。

【参考】
[[Unity] Oculus Goで3Dキャラクターを眺めよう](http://cocoamix.jp/archives/8208)

参考の記事が良くかけていて、この記事はほぼ全て参考の記事のままですが、ウワン＠Unity初心者なりの理解もできたので、記載したいと思います。
###やったこと
（１）Query-Chan modelをマイアセットに追加する
（２）GameObjectをHierarchyに新しく作成：CameraPivotと命名
　　このCameraPivot内（配下）にカメラを配置すると、CameraPivotを回転させることでカメラがキャラクターの周りを旋回する
（３）OVRCameraRigをいい感じの場所に移動
　　ここで一度Build&RunしてOculusGoで確認しました
（４）CameraPivotにRigidbodyをくっつける。
（５）スクリプトでRigidbody.AddTorqueを利用
（６）スクリプトの追加の仕方
（７）HierarchyのQuery-ChanをドラッグしてAnim,Emo,Soundのところへ：とは？
（８）Unity上で実行する
（９）OculusGoで実行する
（１０）スクリプトの編集

###（１）Query-Chan modelをマイアセットに追加する
これは前回の記事と同じで、[ストアのOpen in Unity](https://assetstore.unity.com/packages/3d/characters/query-chan-model-20031)を押してもらえれば以下のようにダウロードページが張り付きます。このページはもともとリンクされていたましたが、検索すると出てきます。
![import_assets.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/c72f0f0d-3ee9-6a07-60b2-5c445fa9b6a4.jpeg)
これをimport押してそのダウンロードしたすべてを再度ProjectにインポートすればOKです。
###（２）GameObjectをHierarchyに新しく作成：CameraPivotと命名
これは、どういうことかというと、CameraPivotというGameObjectを張り付けて、そこにQuery-Chanを載せて（画面上の同じ位置に置いて）、さらにカメラを配下（Hierarchy上）に置いて、RigidBoyという重力や移動が可能なキャラを（GameObjectの属性として）追加してカメラがこのGameObjectの周りをまわるようにする（できる）ということみたいです。
※ここがこの上記参考記事のアイディアのいいところだと思います
![Object_config.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/b9d4a0a2-522c-008e-9627-d5a168a80b44.jpeg)
###（３）OVRCameraRigをいい感じの場所に移動
　　ここで一度Build&RunしてOculusGoで確認しました
移動前のカメラから見える風景はこんな感じでした（笑）
[OculusGo ：足のある風景](https://youtu.be/-bvsWyJf7Ds)
なんか圧倒された。。。（笑）
このカメラをQuery-Chanがちゃんと見える位置に持っていきます。
###（４）CameraPivotにRigidbodyをくっつける
Rigidbodyは、「AddComponent-Physics-」で下の方にあります。
これって、すごく機能というかいろいろできるんですね。
[Unity_Documentation_Rigidbody:Scripting](https://docs.unity3d.com/ScriptReference/Rigidbody.html)
[Unity_Documentation_Rigidbody:manual](https://docs.unity3d.com/Manual/class-Rigidbody.html)
つまり、「The Rigidbody can receive forces and torque to make your objects move in a realistic way. 」ということだそうです。そういう意味で今回はCameraを動かすためにTorqueを使いたくてこれ使っているわけです。
【蛇足】それにしても、Realistic wayというのが、重みありますね。つまりこういうのが仮想現実を支えているんですね。
【蛇足２】ただ、PivotはQuery-Chanのところにあって、カメラは離れたとこにあるのが。。。難しい
###（５）スクリプトでRigidbody.AddTorqueを利用
それでは、[Rigidbody.AddTorque](https://docs.unity3d.com/ScriptReference/Rigidbody.AddTorque.html)のScript例を見てみましょう。
torque	Torque vector in world coordinates.
「Adds a torque to the rigidbody.
Force can be applied only to an active rigidbody. If a GameObject is inactive, AddTorque has no effect.」
ということだそうです。
See Also: AddRelativeTorque, AddForce.
この二つが似たようなScriptなんですね。
Parameters
x	Size of torque along the world x-axis.
y	Size of torque along the world y-axis.
z	Size of torque along the world z-axis.
なので、各軸周りのトルクです。以下が使い方みたいです。
public void AddTorque(float x, float y, float z, ForceMode mode = ForceMode.Force);
そして、肝心な使い方コードは

```csharp
// Rotate an object around its Y (upward) axis in response to
// left/right controls.
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
    public float torque;
    public Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
    void FixedUpdate()
    {
        float turn = Input.GetAxis("Horizontal");
        rb.AddTorque(transform.up * torque * turn);
    }
}
```
因みに、AddForceの例は、turnの定義がないのと、
```rb.AddForce(transform.forward * thrust);```
だけ異なった例になっています。
###（６）スクリプトの追加の仕方【この項追記2018/6/10]
まず、以下のようにProjectのcreateのところでcreate-C#scriptを選んで名前「SceneManager」と入れます。
![add_script.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/06c60ead-034e-319a-b321-3e069f1db3aa.jpeg)
そして、追加されたC#scriptが最下段に現れたら、それをダブルクリックするとVisualStudioが立ち上がり、defaultのコードが入っています。それを以下のコードをコピペして置き換えます。そして上書きします。

さらに、rigidbodyにスクリプトを追加するので、Hierarchyのリストからその親玉のCameraPivotにそのスクリプト「SceneManager」をドラッグドロップします。
すると、自動的に右側のInspector欄に４つの入力欄とともに現れます。
※ここが肝心で単にCameraPivotにscriptをaddするだけではこれが出てきません
![script_dragdrop.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/eeae8732-1a90-9263-e404-5c85e475fcad.jpeg)

###（７）HierarchyのQuery-ChanをドラッグしてAnim,Emo,Soundのところへ：とは？
ここで難問です。どうやったら、以下の状態に持っていけるか。。？？
![Scene_Query-chan.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/4b131416-2362-e190-5e98-43ce2b39a85b.jpeg)

この意味。。。これウワンはHierarchyでなく、横の画面でドラッグしてそれをあの欄のところへ持っていきました。今やってみると、確かにHierarchyでドラッグしてもできました。。。な～んだ。。
###（８）Unity上で実行する
ここまでくると、あとは実行するだけ。
Unity上で▶を押してみます。。ちゃんと動くと思います。
あの硬かったQuery-Chanがふんわり浮かんでいるのが驚きです。
そして、マウスをクリックするとその周りをぐるぐる回り始めます。
###（９）OculusGoで実行する
そして、いよいよBuild&Runそして▶押して、OculusGoで眺めると。。。

そこにはドーンとQuery-Chanの美しいお姿がぶかぷか浮かんでいます！

そして操作スティックの何かを押すと、。。。
まわります。。まわります。。。
これどんどん加速して、目が回る。。。
こんな感じです。。。
[OculusGo：まわるまわるQuery-Chanがまわる♬](https://youtu.be/cG6wsmHzF7w)
###（１０）スクリプトの編集
これじゃかわいそうなので、減速させたい！
ということで、マウスの右クリックで原則させることにしました。
つまり、コードをこんな感じに変更しました。

```csharp
   void kaiten()
    {
        // kaiten !
        // 5,5,5!な斜め方向に。
        cameraPivot.transform.GetComponent<Rigidbody>().AddTorque(new Vector3(5f, 5f, 5f));
    }

    void kaiten2()
    {
        // kaiten !
        // -5,-5,-5!な斜め方向に。⇒右クリックで回転を止める
        cameraPivot.transform.GetComponent<Rigidbody>().AddTorque(new Vector3(-5f, -5f, -5f));
    }

    void Update()
    {
        // 接続確認したいとか
        //if (OVRInput.IsControllerConnected(OVRInput.Controller.RTrackedRemote))

        // GetMouseButtonDownで、UnityEditor上で動作確認できます。
        if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger) || Input.GetMouseButtonDown(0))
        {
            kaiten();
        }
        if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger) || Input.GetMouseButtonDown(1))
        {
            kaiten2();
        }
    }
```
このコードでUnityでは左クリックで回転・加速。。右クリックで減速・逆回転となり、まあ平和なのですが、これがOculusGoだと、~~右クリックが無い。。。~~

さてさて、ここからまたまた試行錯誤。。。
こんなのあるからいけるはずなのに、。。。
[Input.GetMouseButtonDown](https://developer.oculus.com/documentation/unity/latest/concepts/unity-ovrinput/#unity-ovrinput)
一応、以下のような入力定義のはずですが、これはRiftの話なのかな？
[OVRInput](https://developer.oculus.com/documentation/unity/latest/concepts/unity-ovrinput/#unity-ovrinput)
Riftなら
[•Unity マニュアル/•XR/•Unity の xR 入力/•Oculus の入力/](https://docs.unity3d.com/ja/current/Manual/OculusControllers.html)

~~今日のところは、やんぬるかな。。。~~

###まとめ
・初めてのぐるぐる回るの作りました
・Unity上では加速・減速・逆回転・ゆっくり眺めることができました

・OculusGoのマウス右ボタンに代わるやり方ないのかなぁ～
　　ちなみに、右手左手の持ち替えはやってみたけど、同じですね（笑）
　　あと、戻るボタン連打すると効果小さいけど確かに減速しましたが、。。。？？

【追記】逆回転できました！
反応が鈍かっただけで、以下のようにトルク大きくしたら、逆回転も反応して普通に回るようになった。。。こうなると自分の方に向かせたくなる♬
以下YouTubeで。。。
[ Oculus-Unity連携：Query-Chanが回る。。逆回転も出来た](https://youtu.be/BE8cgwavdrA)
※因みに、引き金引く方が速いので右（１）、上面が遅い方で左（０）だった！
【追記２】並行移動要素を入れたら、よりゲーム性が増しました！
[Unity-OculusGo連携：いよいよQuery-Chanとドッキング♬](https://youtu.be/l9rFdKR-gHg)
こんな感じでクリックするたびに並行移動しています。
<a href="http://www.youtube.com/watch?feature=player_embedded&v=l9rFdKR-gHg
" target="_blank"><img src="http://img.youtube.com/vi/l9rFdKR-gHg/0.jpg" /></a>

**並行移動は以下のコードをkaiten等に入れて実現しています**

```csharp
cameraPivot.transform.GetComponent<Rigidbody>().MovePosition(transform.position + 10*transform.forward * Time.deltaTime);
```

```csharp
    void kaiten()
    {
        // kaiten !
        // 5,5,5!な斜め方向に。
        cameraPivot.transform.GetComponent<Rigidbody>().AddTorque(new Vector3(5f, 5f, 5f));
    }
    void kaiten2()
    {
        // kaiten !
        // -10,-10,-10!な斜め方向に。⇒右クリックで回転を止める
        cameraPivot.transform.GetComponent<Rigidbody>().AddTorque(new Vector3(-10f, -10f, -10f));
    }
```
###[参考先のScriptコード](http://cocoamix.jp/archives/8208)

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class SceneManager : MonoBehaviour
{
 
    // クエリちゃん設定
    public QueryAnimationController queryAnim = null;
    public QueryEmotionalController queryEmo = null;
    public QuerySoundController querySound = null;
 
    // 回転対象
    public GameObject cameraPivot = null;
 
    private void Awake()
    {
        // 【Unite Tokyo 2018】Oculusで作るスタンドアローン・モバイルVRコンテンツ
        // https://www.slideshare.net/UnityTechnologiesJapan002/unite-tokyo-2018oculusvr-96453609/UnityTechnologiesJapan002/unite-tokyo-2018oculusvr-96453609
        // 上記スライドを参考にした設定
 
        // アイバッファ解像度 scale 1.0 == 1024x1024
        UnityEngine.XR.XRSettings.eyeTextureResolutionScale = 1.25f;
 
        // 外枠側のレンダリング設定。>>HIGH　外側の解像度が減っていく
        OVRManager.tiledMultiResLevel = OVRManager.TiledMultiResLevel.LMSLow;
 
        // 72Hzモード（フレームレートは上がるが綺麗）
        OVRManager.display.displayFrequency = 72.0f;
    }
 
    void Start()
    {
        // 浮いてるアニメーション再生
        queryAnim.ChangeAnimation(QueryAnimationController.QueryChanAnimationType.FLY_IDLE);
 
    }
 
    void kaiten()
    {
        // kaiten !
        // 5,5,5!な斜め方向に。
        cameraPivot.transform.GetComponent<Rigidbody>().AddTorque(new Vector3(5f, 5f, 5f));
    }
 
    void Update()
    {
        // 接続確認したいとか
        //if (OVRInput.IsControllerConnected(OVRInput.Controller.RTrackedRemote))
 
        // GetMouseButtonDownで、UnityEditor上で動作確認できます。
        if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger) || Input.GetMouseButtonDown(0))
        {
            kaiten();
        }
    }
}
```