VRTK-3.2.1のSDKを自作する

VRTKはSDKという概念でVRデバイスの切り替えを実装しています。

![sdk.jpg](https://qiita-image-store.s3.amazonaws.com/0/59664/2f043219-0859-b2d3-1069-84d3eadc9cd7.jpeg)

Simulator(WASDで移動し、Mouseで回頭する)が使いづらいので自作してみよう

https://github.com/ousttrue/VRTK_MouseGrab

# Simulatorをコピーして名前を変える
## Simulatorの構成を確認

![sim.jpg](https://qiita-image-store.s3.amazonaws.com/0/59664/cfebc2ad-1fd6-6bbf-9f52-307ded0c8f8a.jpeg)

* SDK_SimXXX というのがSDKクラスを継承
* SDK_ControllerSim コントローラーのMonoBehaviour
* SDK_InputSimulator コントローラーのMonoBehaviour

となっております。

## 名前を決めてフォルダを作る

マウスカーソルの位置に手が動き、左クリックがトリガー、右クックがグリップとして振るまうSDKを作ってみたい。
名付けて `MouseGrab` 。

## Systemを作る

`Simulator/SDK_SimSystem` を `Control-D` で複製して `MouseGrab` フォルダに移動。`SDK_MouseGrabSystem` にリネームする。
中身のSim, Simulator等を適当に置き換える。

```cs
    [SDK_Description("MouseGrab", null, null, "Standalone")]
    public class SDK_MouseGrabSystem : SDK_BaseSystem
    {
    }
```

属性でSDK名を定義している

## Controller用のMonoBehaviourを作る
SDK内に相互参照があるので適当な順に作ります。

`Simulator/SDK_ConstrollerSim` を `Control-D` で複製して `MouseGrab` フォルダに移動。`SDK_ControllerMouseGrab` にリネームする。
中身のSim, Simulator等を適当に置き換える。

## Controllerを作る

`Simulator/SDK_SimConstroller` を `Control-D` で複製して `MouseGrab` フォルダに移動。`SDK_MouseGrabController` にリネームする。
中身のSim, Simulator等を適当に置き換える。

## Input用のMonoBehaviourを作る

`Simulator/SDK_InputSimulator` を `Control-D` で複製して `MouseGrab` フォルダに移動。`SDK_InputMouseGrab` にリネームする。
中身のSim, Simulator等を適当に置き換える。

hintCanvas 削除。使っているところも削除。
hintText 削除。使っているところも削除。
showControlHints 削除。使っているところも削除。
crossHairPanel 削除。使っているところも削除。

## Boundariesを作る

`Simulator/SDK_BoundariesSimulator` を `Control-D` で複製して `MouseGrab` フォルダに移動。`SDK_BoundariesMouseGrab` にリネームする。
中身のSim, Simulator等を適当に置き換える。

## Headsetを作る

`Simulator/SDK_HeadsetSimulator` を `Control-D` で複製して `MouseGrab` フォルダに移動。`SDK_HeadsetMouseGrab` にリネームする。
中身のSim, Simulator等を適当に置き換える。

## Prefabを作る

セットアップ済みのprefabを作る。
Simulatorから改造するのでシーンにVRSimulatorCameraRigをインスタンス化する。

MouseGrabに名前を変える。
MouseGrabを `SDK/MouseGrab` フォルダにドラッグして新しくPrefab化する。
改造する。

MouseGrabの `SDK_Selection` をMouseGrabに変更する。

![selection.jpg](https://qiita-image-store.s3.amazonaws.com/0/59664/ce4f3cbc-4d38-ef6f-b83c-c813ff73a55b.jpeg)

VRSimulatorCameraRigの `SDK_InputSimulator` を　`SDK_InputMouseGrab` に置き換える

Canvas削除

LeftHandとRightHandの `SDK_ControllerSim` を `SDK_ControllerMouseGrab` に置き換える

Prefabをapplyする。

## 使ってみる

新規シーン。
MainCamera削除。
CreateEmpty。`VRTK_SDK` にリネーム。
MouseGrab prefab を VRTK_SDK の子にする。
VRTK_SDKに `VRTK_SDK Manager` をアタッチ。AutoPopulateを押す。

実行してみる。

![ss.jpg](https://qiita-image-store.s3.amazonaws.com/0/59664/531a5226-f1e1-5c53-f4e5-10451ac3520d.jpeg)

エラーが無いことを確認。
では、本題に入ろう。

# 改造して動きを変える
## キーアサイン

* WASD 前後左右に移動(元から)
* 矢印キーでHeadの向き変更
* マウスカーソルでHeadの向き変更をしない。マウスカーソルのスクリーン位置に手を動かす。
* 左クリックでトリガー(元から)
* 右クリックでグリップ(元から)

こんな感じで

## SDK_InputMouseDragを改造

### Headの向き
neckじゃなくてtransformを回転することにした。

```cs
        const float _rotDegrees = 15.0f;
        Vector3 _rot;
        private void UpdateRotation()
        {
            if (Input.GetKeyDown(KeyCode.DownArrow))
            {
                _rot.x += _rotDegrees;
            }
            if (Input.GetKeyDown(KeyCode.UpArrow))
            {
                _rot.x -= _rotDegrees;
            }
            if (Input.GetKeyDown(KeyCode.LeftArrow))
            {
                _rot.y -= _rotDegrees;
            }
            if (Input.GetKeyDown(KeyCode.RightArrow))
            {
                _rot.y += _rotDegrees;
            }
            transform.rotation = Quaternion.Euler(_rot);
        }
```

### スクリーン位置に手を移動

深度決め打ちで。

```cs
        float _distance = 2.0f;
        private void UpdateHands()
        {
            var c = Camera.main;
            Ray ray = c.ScreenPointToRay(Input.mousePosition);
            currentHand.position = c.transform.position + ray.direction * _distance;
        }
```

### モード無用

isHandを削除して使っているところを適当に修正。

```cs
// 毎フレーム
                UpdateHands();
                UpdateRotation();
```

### Gizmo

カメラ位置とレイを描画

```cs
        private void OnDrawGizmos()
        {
            var c = Camera.main;

            Gizmos.color = Color.green;
            Gizmos.matrix = c.transform.localToWorldMatrix;
            Gizmos.DrawFrustum(Vector3.zero, 
                Camera.main.fieldOfView, 
                Camera.main.farClipPlane, 
                Camera.main.nearClipPlane, 
                Camera.main.aspect);
            Gizmos.matrix = Matrix4x4.identity;

            Gizmos.color = Color.red;
            Gizmos.DrawLine(c.transform.position, currentHand.position);
        }
```

fovを40にして、farを20にしてみた。

![raycast.jpg](https://qiita-image-store.s3.amazonaws.com/0/59664/5fa9089b-707e-40ee-31fc-6726525ac9ac.jpeg)

### 完成
左クリックでGrabできて横に投げることができた。

https://github.com/ousttrue/VRTK_MouseGrab/releases

# 参考

* http://negi-lab.blog.jp/VRTK_3_2_1_Setup
* http://negi-lab.blog.jp/VRTK_Grab