Unity未経験者がCodelabのCardboardチュートリアルをやってみた


せっかく手元にGoogle I/Oで貰ったCardboardがあるので、Unity触ったこと無いけどCodelabの"[Cardboard Unity Codelab](https://io2015codelabs.appspot.com/codelabs/cardboard-unity#1)"をやってみた。
Unityは未経験なので用語その他間違っているところはあると思います。

一部、Unity4系の前提で書かれているためか手順通りにできない場所があったけど基本的には元ページの内容通りにやっていくだけ。
かんたんかんたん。

## Unity インストール

なにはともあれとりあえず最新のUnityをダウンロード＆インストール。
http://unity3d.com/jp/get-unity/update

自分はUnity 5.0.2をインストールしました。

## サンプルコードの入手

### Cardboard SDKのダウンロード

適当なディレクトリにクローンする。

```
git clone https://github.com/googlesamples/cardboard-unity.git
```

### サンプルゲームのダウンロード

アセットパッケージを含んだサンプルゲームをダウンロードする。
https://github.com/googlesamples/io2015-codelabs/blob/master/cardboard-unity/assets/lollygagger_step0.unitypackage?raw=true

## サンプルゲームの実行

### Unity起動

インストールしたUnityを起動する。
初めて起動するとライセンスの選択画面が出るので"Personal Edition"を選択する。
![1_License.png](https://qiita-image-store.s3.amazonaws.com/0/53706/6ec3597f-1259-8364-d74e-a49329a9e6d5.png "1_License.png")

アカウントは持っていないので"Create Account"を選択。
![2_Login.png](https://qiita-image-store.s3.amazonaws.com/0/53706/10e5138c-ae90-c04e-8897-b9bc796c866d.png "2_Login.png")

アカウント情報を入力して"OK"を押下。
![3_CreateAccount.png](https://qiita-image-store.s3.amazonaws.com/0/53706/4cd0005b-f2be-6df4-9eb5-0f855d49623a.png "3_CreateAccount.png")

これでUnityを使いはじめる準備が完了！
![4_Gone.png](https://qiita-image-store.s3.amazonaws.com/0/53706/d455dc78-69fe-a8dd-8b1f-91df1db77a77.png "4_Gone.png")

### プロジェクトの開始

Unityを起動すると下の画面が表示されます。
![5_start.png](https://qiita-image-store.s3.amazonaws.com/0/53706/ccb4c0ee-1866-c845-8374-d226215f2b55.png "5_start.png")

Codelabの手順では起動したらAndroid SDK Locationを設定しろとなっていますが、メニューのPreferenceがグレーアウトされているので先にプロジェクトを作ってしまいます。

プロジェクト名は"Lollygagger_cardboard"、3Dを選択しておきます。
![6_project.png](https://qiita-image-store.s3.amazonaws.com/0/53706/6046774c-7f22-2e97-b2ce-e71ceb046a57.png "6_project.png")

プロジェクトが開始したら先ほど飛ばしたAndroid SDK Locationの設定を行います。
Preferences > External Tools > Android SDK Locationと選択し、Android SDKがインストールされている場所を指定します。

### サンプルゲームのassetsインポート

Assets > Import Package > Custom Packageでダウンロードしてきた`lollygagger_step0.unitypackage`をインポートする。

インポート後、"API Update Required"というダイアログが出るので"I Made a Backup. Go Ahead!"を選択。
![7_apiUpdate.png](https://qiita-image-store.s3.amazonaws.com/0/53706/08082d6c-20d5-8935-8b50-95fcf04e56fc.png "7_apiUpdate.png")

### Android playerの構成

Androidで実行できるように構成を行う。
わかりやすいGif動画がCodelabに掲載されているのでそちらも参照。

1. File > Build Settings...を選択
2. リストからAndroidを選択
3. Switch Platformを選択
4. AssetsのMainMenuを"Scenes In Build"にドラッグ&ドロップ
5. 同じくAssetsのGameSceneを"Scenes In Build"にドラッグ&ドロップしてMainMenuの下に配置
6. "Player settings..."をクリック
7. "Resolution and Presentation"をクリックして展開、Default OrientationをLandscape Leftに変更
8. "Other Settings"をクリックして展開、Bundle Identifierにパッケージ名を設定
9. プロジェクトを保存する

### サンプルゲームの実行

同じBuild Settingsの画面で"Build And Run"をクリック。
ファイル名を聞かれるのでLollygagger.apkで保存、しばらく待って繋いでいる実機でゲームが起動すれば成功。
![2015-06-06 10.10.23.png](https://qiita-image-store.s3.amazonaws.com/0/53706/235d5b5e-907a-3ac6-2ebd-d80926c9c6f4.png "2015-06-06 10.10.23.png") ![2015-06-06 10.10.35.png](https://qiita-image-store.s3.amazonaws.com/0/53706/4348af30-415b-4a97-6d4b-065688307bb0.png "2015-06-06 10.10.35.png")

## メインメニューシーンにCardboardを追加する

### Cardboard SDKをプロジェクトに追加

Assets > Import Package > Custom Packageで`CardboardSDKForUnity.unitypackage`を選択してインポートする。
このとき、すべてのファイルをインポートするのではなくDemo Scene フォルダと Legacy/Demo Scene の選択を解除してからインポートする。
![import.png](https://qiita-image-store.s3.amazonaws.com/0/53706/7eb79075-7aa7-d558-e0d0-30a2316cb4ab.png "import.png")

最初のインポートの時と同様にAPI Update Requiredのダイアログが表示されるので同じく"I Made a Backup. Go Ahead!"を選択。

### メインメニューにcardboardモードを追加する

Cardboardでメニューを表示するためにステレオカメラと関係するスクリプトを追加する。

1. プロジェクトエクスプローラからAssetsフォルダのMainMenuをダブルクリック
2. Scene HierarchyからMain Cameraを選択
3. メニューから Component > Cardboard > Update Stereo Cameras を選択

### UIをworld spaceに変更する

Screen SpaceからWorld Spaceに変換する。

1. HierarchyウインドウからCanvasを選択して、Inspectorパネルで以下の変更を行う
	- Render ModeをWorld Spaceに変更
	- Rect Transformで位置を(0, 0, 750)に変更
	- 幅640、高さ480に変更
	- Pivotを(0.5, 0.5)に変更
	- Scaleを(1, 1, 1)に変更
2. 以下の手順でMain CameraをCanvasに関連付ける
	- HierarchyウインドウでCanvasを選択
	- InspectorパネルでEvent Cameraの右にある小さい丸をクリック。出てきたウインドウのSceneタブでMain Cameraを選択

![eventcamera.png](https://qiita-image-store.s3.amazonaws.com/0/53706/1cb94c74-d8f8-773f-064f-2e25779c38a0.png "eventcamera.png")

### Cardboardモードボタンをメニューに追加する

Cardboardモードをオンオフするためのボタンを追加する。

1. プロジェクトエクスプローラでAssets/Prefabs/cardboardButtonを見つける
2. HierarchyウインドウでCanvasとPanelを展開
3. cardboardButtonをPanelの直下にドラッグ&ドロップ

## Cardboardモードのスクリプトを書く

### Canvasに新しいスクリプトを追加する

1. HierarchyウインドウからCanvasを選択
2. InspectorパネルでAdd Componentボタンをクリック、一覧の一番下にあるNew Scriptを選択
3. スクリプト名はCardboardModeMgr、言語はCSharpのままでCreate And Addをクリック
4. プロジェクトエクスプローラでCardboardModeMgr.csをダブルクリックして開く
5. 以下のコードをコピペして保存

```csharp
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using UnityEngine.UI;

public class CardboardModeMgr : MonoBehaviour {
    
    // We need a reference to camera which 
    // is how we get to the cardboard components.
    public GameObject mainCamera;


    public void Start()
    {
        // Save a flag in the local player preferences to initialize VR mode
        // This way when the app is restarted, it is in the mode that was last used.
        int doVR = PlayerPrefs.GetInt("VREnabled");
        Cardboard.SDK.VRModeEnabled = doVR == 1;
        CardboardHead head = mainCamera.GetComponent<CardboardHead>();
        head.enabled  = Cardboard.SDK.VRModeEnabled;
    }

   // The event handler to call to toggle Cardboard mode.
    public void ChangeCardboardMode ()
    {
        CardboardHead head = mainCamera.GetComponent<CardboardHead>();
        if (Cardboard.SDK.VRModeEnabled) {
            // disabling.  rotate back to the original rotation.
            head.transform.localRotation = Quaternion.identity;
        }
        Cardboard.SDK.VRModeEnabled = !Cardboard.SDK.VRModeEnabled;
        head.enabled  = Cardboard.SDK.VRModeEnabled;
        PlayerPrefs.SetInt("VREnabled", Cardboard.SDK.VRModeEnabled?1:0);
        PlayerPrefs.Save();        
    }
}
```

### VRの入力ハンドリング

Cardboardのボタンクリックをハンドリングするため入力モジュールを追加する

1. HierarchyウインドウでEventSystemを選択
2. メニューからComponent > Scripts > Gaze Input Moduleを選択

### カメラとゲームオブジェクトを関連付ける

視線でカメラや操作ができるように設定する

1. HierarchyウインドウでCanvasを選択
2. Cardboard Mode MgrのMain Cameraの右にある小さな丸をクリック
3. シーンタブからMain Cameraを選択

### クリックイベントとスクリプトを関連付ける

1. HierarchyウインドウでCanvas/Panel/buttonCardboardを選択
2. InspectorパネルのOn Click()セクションになにもなければ"+"をクリック。自分の環境では最初から一つあったのでそれを設定変更
	- 最初の項目をRuntime Onlyにする
	- 下の項目の小さな丸をクリック、出てきたウインドウのシーンタブからCanvasを選択
	- 右の項目でCardboardModeMgr.ChangeCardboardMode()を選択

![onclick.png](https://qiita-image-store.s3.amazonaws.com/0/53706/c48507b9-abd1-d787-6475-8e3e904e5950.png "onclick.png")

## Main Menuの動作確認

上部にある再生ボタンをクリック、メインメニュー画面でCardboard Buttonをクリックした後、Cardboardモードに切り替われば成功。
![test.png](https://qiita-image-store.s3.amazonaws.com/0/53706/10270308-cc19-a9c8-f22f-8d1571260c62.png "test.png")

## Game SceneにCardboardを追加

手順はMain Menuの時とほぼ同じなので簡単に

### Game SceneにCardboard Viewを追加

1. エクスプローラでGame Sceneをダブルクリック
2. HierarchyウインドウでPlayer/Main Cameraを選択
3. メニューからComponent > Cardboard > Update Stereo Camerasを選択

### GazeInputModuleをEvent Systemに追加

1. HierarchyウインドウでEventSystemを選択
2. メニューからComponent > Scripts > Gaze Input Moduleを選択
3. Codelabの手順には無いが、EventSystemのInspectorパネルでGaze Input ModuleのVr Mode Onlyにチェックを入れる。これを入れてないとメニューの通常モードでちゃんと操作できなくなる。

### 一旦動作確認

シーンとプロジェクトを保存して、Build And Run!

起動してCarboad Modeをタップすると下の画面になり、ゲームの画面もちゃんと表示されます。
![2015-06-06 13.00.34.png](https://qiita-image-store.s3.amazonaws.com/0/53706/2703f4bf-c769-adb0-0912-3a58f20caa85.png "2015-06-06 13.00.34.png")

### プレイヤーの視線での操作をベースにする

VRモードでは視線の操作などスマホのタッチパネルで行っていた操作をプレイヤーの視線方向で行えるようCardboard SDKがハンドルしてくれます。
なのでVRモードが有効なとき、タッチ操作での計算を動かないようにしてCPUの負荷を下げることができます。

1. プロジェクトエクスプローラでAssets/Scripts/MouseLookingを開く
2. `Update()`メソッドの一番上に以下のコードを貼り付ける

```csharp
if (Cardboard.SDK.VRModeEnabled) {
           return;    
}
```

### Cardboardボタンを使った操作を追加する

Cardboardには操作用のボタンがひとつ付いています。このボタンでゲームを操作できるようにします。

Assets/Scripts/Shootingを開き、以下のコードを

```csharp
if(Input.GetButtonUp("Fire1") && ! GameManager.Instance.IsMenuShowing)
```

次のように入れ替える

```csharp
if((Cardboard.SDK.CardboardTriggered || Input.GetButtonUp("Fire1")) && 
     !GameManager.Instance.IsMenuShowing)
```

ここでもう一度実行してみると、ゲーム画面でCardboardのボタンで玉を撃てるようになっています。
![2015-06-06 16.28.38.png](https://qiita-image-store.s3.amazonaws.com/0/53706/2243afa0-eb81-bd1f-b9df-cb836f260abf.png "2015-06-06 16.28.38.png")

### エンディングメニューをVRに対応させる

現状では、ゲーム最後のメニューで操作ができないのでこの画面もVRに対応させる。

1. Game SceneのHierarchyウインドウでCanvasを選択
2. Inspectorパネルで以下の設定変更
	- Render ModeをWorld Spaceに変更
	- 位置を(25, 0, 135)に変更
	- 幅240、高さ180に変更
	- Pivotを(0.5, 0.5)
	- Scaleを(0.04, 0.04, 0.04)
3. Event CameraをMain Cameraに設定する

![2015-06-06 16.29.33.png](https://qiita-image-store.s3.amazonaws.com/0/53706/cbb995b3-c54a-8832-1fcd-b7dd919da1c6.png "2015-06-06 16.29.33.png")

## おわり

これでCodelabのチュートリアルは終わりです！
Unityは使ったこと無いけど、今回のような手順でできるなら既存のものをCardboard化するのはそんなに難しくないのかな？