Unity でVRのテレポートを一番簡単に実現する方法

# 概要
この記事は、VR上でよく目にする「テレポート」を実現するための手法を書いてあります。ハンドデバイスの先に放物線状に線が表示されて、ボタンを押すとその着地点にワープするというアレです。

順番としては

1. VRのためのセットアップ
1. VRTKインストール(Oculus Integrationも)
2. ゲーム画面のセットアップ
3. デバイス入力
4. テレポートシステム

とやっていきます。


# システム要件

- Unity 2018.3.0f2
- Oculus GO
- Asset Storeで無料で取得できるアセット
    - VRTK (4.0.0)
    - Oculus Integration (1.36)

# Android プラットフォームに切り替え
1. Androidを選択
2. Texture Compression をASTCに
3. Switch Platform をクリック

    <img width="500" alt="Build_Settings_と_Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_PC__Mac___Linux_Standalone__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/693b90dd-f15c-48a6-d137-831d089066a4.png">

# PlayerSettings の設定

Oculus GO用にPlayerSettingsをいくつか変更します。

### XR Settings 
1. Virtual Reality Supported にチェック
2. ＋ボタンをクリック
3. Oculus を選択

    <img width="300" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/98a9654b-cdf9-1cdb-79a3-ce5d925639ce.png">

### Other Settings
1. Package Name を適当に自分のドメインを入れる
2. Minimum API Level を「Android 4.4 'KitKat' (API level 19)」を選択
3. Scripting Runtime Version を「.NET 4.x Equivalent」（デフォルトでなっているはず）

    <img width="320" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/48bd8fa1-6abd-c128-2ef9-c7ce9cb58423.png">

# VRTKとOculus Integrationのインストール

ハンドデバイスやテレポートシステムを簡易的に使うには「VRTK」が一番簡単で良いだろうということで、VRTKを使うことにします。VRTKは最新版のv4.0.0を使うことにします。ただし、最新版はGitHubにしかない(2019/5/22現在)ので、gitコマンドで持ってくる必要があります。

ターミナル（もしくはcmd）で プロジェクトの Assets/ 以下に行って、以下のコマンドを打ちます

    git clone --recurse-submodules https://github.com/ExtendRealityLtd/VRTK.git
    cd VRTK
    git submodule init && git submodule update

Gitコマンドがない、というかたは

https://github.com/ExtendRealityLtd/VRTK

からダウンロードしてください。その場合は

https://github.com/ExtendRealityLtd/Zinnia.Unity/tree/91b8e16fc366cf6022440ed1efbe7ce4e636eae4

もダウンロードして

Assets/VRTK/Dependency/Zinnia.Unity/

に配置する必要があるので気をつけてください。

なお、現段階(2019/5/22現在)では以下のようなエラーが出てしまいます。

    Assets/VRTK/Dependencies/Zinnia.Unity/Editor/Data/Collection/ObservableListEditor.cs(17,41): error CS0246: The type or namespace name 'InspectorEditor' could not be found (are you missing a using directive or an assembly reference?)

仕方ないので、手っ取り早く以下のファイルを__消します__

    Assets/VRTK/Dependencies/Zinnia.Unity/Editor/Data/Collection/ObservableListEditor.cs

正常にインポートできれば、最後にウィンドウが出ます。「Add Input Mappings」を押します。
<img width="320" alt="_VRTK__-_Manage_Input_Mappings.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/70acbb22-a2d7-cc17-b56b-31afddb21fbf.png">

Oculus Integration は AssetStore からダウンロードしてインポートします。ただし全部必要ないので、「Platform」「VR」だけチェックが入るようにしましょう。

<img width="350" alt="Import_Unity_Package.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/06029ab9-2c19-a869-6b29-07cea5416ee0.png">

# ゲーム画面のセットアップ

とりあえずステージとなるものとプレイヤーとなるものを作っています。
（ここでやっていることはこの通りではなくて良いです。ステージとなるCubeと、プレイヤーとなるオブジェクトを作っていれば何でも良いです）

1. GameObject→3DObject→Cube で立方体を作って、Position(0,-1,0), Scale(20,1,20)。名前をFloorにする。
2. GameObject→3DObject→Capsule でカプセルを作って、Position(0,0,0), Scale(1,0.5,1)。名前をHeadにする。
3. GameObject→3DObject→Cube で立方体を作って、Position(0,0,0.2), Scale(0.7,0.2,0.7)。名前をHMDにして、Headにドラッグアンドドロップ（以下D&D）して子オブジェクトにする.
4. GameObject→Create Empty で空オブジェクトを作って、Position(0,0,0)で名前をPlayer にする.
5. Head を Player にD&Dして子オブジェクトにする.

こんな感じになるかと思います。（ちなみにこのプレイヤーは次回に使います。この時点では動きません）
<img width="637" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/a93f5e97-c429-42ff-91b1-455c35267d24.png">

# VRTKのセットアップ

まずはVRTK で基本となる「TrackedAlias」を設定します。これは様々なデバイスを利用できるようにVRTK側でまとめてくれているものです。これを経由することでいちいちOculusはこれでVIVEはこれでとか設定しなくても良くなるというものです。

Assets/VRTK/Prefabs/CameraRig/TrackedAlias/TrackedAlias.prefab 

をシーンにD&Dします。
<img width="491" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/742bcf77-43b5-a55c-8643-e90a5f0f3e3e.png">

次にOculus のカメラ

Assets/Oculus/VR/Prefabs/OVRCameraRig.prefab 

もシーンにD&Dします。
シーンに元々ある MainCamera は削除しておきましょう。
<img width="440" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/fd2d7f50-5363-d195-1f51-0cda086c4daa.png">

シーンのルートに空オブジェクト（Position(0,0,0)に）を作って「OVRCameraRigRoot」という名前にして、それに先程の「OVRCameraRig」オブジェクトをD&Dして子オブジェクトにします。

シーン上の「OVRCameraRig」を選択して、OVRManager の項目で以下の項目を変更します。

- Tracking Origin Type → Floor Level
- Reset Tracker On Load →　チェック

<img width="274" alt="Unity_2018_3_0f2_-_Game_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/9de83614-57b7-d737-41d7-d8e38dee79da.png">


「OVRCameraRigRoot」に「Linked Alias Association Collection」をアタッチします。そして以下のように設定します。

- OVRCameraRigRoot → PlayArea
- OVRCameraRigRoot>OVRCameraRig → Headset
- OVRCameraRigRoot>OVRCameraRig>CenterEyeAnchor → Headset Camera
- OVRCameraRigRoot>OVRCameraRig>LeftHandAnchor → Left Controller
- OVRCameraRigRoot>OVRCameraRig>RightHandAnchor → Right Controller

<img width="530" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/d889c695-f2a9-df2c-ae19-9bce9c64d725.png">


TrackedAliasを選択して、Inspector（右の詳細画面）の一番下にある Elements の Size を 1 にします。
Element 0 のところに先程作った「OVRCameraRigRoot」をD&Dします。
<img width="511" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/7c08a661-d863-4acb-9cbe-3974034146aa.png">

# デバイス入力

VRTKでデバイス入力をするためにはまず、VRTKの基本となる部分を進めます。

Assets/VRTK/Prefabs/CameraRig/UnityXRCameraRig/InputMappings/UnityXR.OpenVR.RightController.prefab

をシーンにD&D
<img width="503" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/cd7f6297-7c5d-62d8-5e4b-07241fe9ff14.png">

続けて

- Assets/VRTK/Prefabs/Pointers/ObjectPointer.Curved.prefab

をシーンにD&D
<img width="495" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/7e0c4e5d-491e-1f7b-3984-42e47e415a89.png">

PointerFacadeの各項目に下のようにアサインします。

- TrackedAlias>Aliases>RightControllerAlias → Folow Source 
- UnityXR.OpenVR.RightController>Trackpad>Touch[17] → Activation Action
- UnityXR.OpenVR.RightController>Trackpad>Press[9] → Selection Action


<img width="540" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/019eee68-2eb5-e266-242e-7de6701264b8.png">

一旦このシーンをセーブしておいてください。ファイル名は"Game"とかにしておきましょう。
この段階でOculus GO にビルドしてみましょう。デバイスのタッチ部に触ると、棒から放物線が出るはずです。

# テレポートシステム

Assets/VRTK/Prefabs/Locomotion/Teleporters/Teleporter.Instant.prefab をシーンにD&Dします。

<img width="546" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/cf05021b-2268-9ede-8600-35c1a8423980.png">

シーンに配置した「Teleporter.Instant」を選択して、TeleportFacadeに以下のようにアサインします。

- TrackedAlias>Aliases>PlayAreaAlias → Target
- TrackedAlias>Aliases>HeadsetAlias → Offset
- TrackedAlias>Aliases>SceneCameras → Camera Validity

<img width="532" alt="Unity_2018_3_0f2_-_SampleScene_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/3fab27b5-fbdf-c830-9181-417fe78eae3b.png">

次にパッドボタンを押した時にテレポートが発動できるようにします。
「ObjectPointer.Curved」を選択して、

1. 一番下の方にある「Selected (Event)」の「＋」ボタンをクリック
1. 「Teleporter.Instant」を項目にD&D
2. 「No Function」 を 「TeleporterFacade→Teleport」 に変更

<img width="533" alt="Unity_2018_3_0f2_-_Game_unity_-_MultiplayTest_-_Android__Metal_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/3a7b48a5-31a0-5d8e-af92-a9970a05fb71.png">

これで再度シーンをセーブしてOculus GOでビルドしてみて、ちゃんとテレポートシステムが作動しているか確認してください。

![GO01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/3e123b79-1b91-82a7-8831-3a7eb34933fc.gif)

次回は「UnityでマルチプレイVRを一番簡単に実現する方法」を解説していきます。