VR空間でやる夫作品を読んでみる (β)

昨日、今日とハッカソンがあり初参加してきたのですが、
そこで *VR空間でやる夫作品を読む* というプロダクト?を作成してきました。
※完成度は超絶低いです

備忘録的に手順をメモしておこうと思います


## 環境

OSX 10.11
Unity 5.4.0f3 Personal
CardBoard SDK 

## 作成の流れ

### 1. Unity のインストール
  [公式](https://unity3d.com/jp/get-unity/download)から

### 2. CardBoard SDKの入手
  今回VR化するにあたってGoogle Cardboard SDK というのものを使用しました。

  Google Cardboard とは

  >_Google Cardboardとは折りたたみボール紙製の本体に手持ちのスマートフォンと組み合わせてことで完成するHMD。レンズが部品として付属し、目の周辺に装着することでバーチャルリアリティ体験ができる[1]。_
[wikipedia](https://ja.wikipedia.org/wiki/Google_Cardboard)より
  
  こちらのSDKとUnityを用いることで非常に安価にVRコンテンツの作成ができるようです。
  今回はこのスマートフォンを組み合わせることができるHMDを
持ってる方がいらっしゃったのでお借りしました。

  入手先は[公式サイト](https://developers.google.com/vr/unity/download)より
  Unity用のSDKを適当なディレクトリへクローンします

   ```
   $ git clone https://github.com/googlevr/gvr-unity-sdk.git
   ```
　
### 3. Unity でプロジェクトの作成
  
  Unityで適当なプロジェクトを作成

### 4. Cardboard SDK のインポート

　プロジェクトが開いたら先ほどダウンロードしたSDKをインポートします
  

  Assets > Import Package > Custom Package...
![スクリーンショット 2016-08-21 21.35.01.png](https://qiita-image-store.s3.amazonaws.com/0/55219/7d82521c-0531-df32-5a9a-fb931ec5a7a0.png)

  先ほどcloneしてきたディレクトリにある`GoogleVRForUnity.unitypackage`を指定します
![スクリーンショット 2016-08-21 21.39.10.png](https://qiita-image-store.s3.amazonaws.com/0/55219/2374022a-d30b-b789-71e4-645db8cf3d56.png)

  するとインポートするものの選択画面?になります。
  何が必要かわからないので全てインポートしました()
![スクリーンショット 2016-08-21 21.40.44.png](https://qiita-image-store.s3.amazonaws.com/0/55219/371fd6ac-720f-3011-8f9f-8554b69a01ca.png)


### 5. HeadSet DemoScene を開く

  画面下の Projectタブにて
  Assets > GoogleVR > DemoScenes > HeadsetDemo を選択

![スクリーンショット 2016-08-21 22.15.46.png](https://qiita-image-store.s3.amazonaws.com/0/55219/1f3db40f-7d45-b288-94a2-ca35c3f4c4b9.png)


   Headトラッキングが体験できるデモが入っています。
   今回はこちらをベースに開発を進めました

### 6. IPAモナーフォントのダウンロード, インポート

   AAを崩れないようにするために[IPAモナーフォント](http://www.geocities.jp/ipa_mona/)をダウンロードします

   ダウンロードしたら Unity にインポートするために Resources フォルダを作成します

   画面下の `Assets` を右クリックして、現れたメニュから フォルダを作成します
![スクリーンショット 2016-08-21 22.19.40.png](https://qiita-image-store.s3.amazonaws.com/0/55219/5192b538-295a-b952-d65c-aa5046216b83.png)

   Assets の下に Resources フォルダを作成することで外部リソースファイルに
   スクリプトからアクセスが可能となるようです
   
   フォルダを作成したらコンテキストメニューから
   Import New Asset を選択し、インポートします

   ![スクリーンショット 2016-08-21 22.23.13.png](https://qiita-image-store.s3.amazonaws.com/0/55219/917c0ff7-12e9-92af-d312-841ad22ada44.png)

   解凍したフォルダの中の fontsディレクトリ以下の ipagp-mona.ttf を選択します
   

### 7. やる夫のAAをテキストファイルにしてインポート

   やる夫のAAをスクリプトから読み込むためにテキストファイルにして,
   Resources フォルダ以下に AAフォルダを作成し、そこにインポートします

   今回は以下を3つのファイルに分けてインポートします

   ```Resources/AA/aa_1.txt
  　 　 　　　＿＿＿_ 
　 　　　／　　 　 　＼ 
　　　／　 _ノ 　ヽ､_　 ＼ 
　 ／ oﾟ(（●）) (（●）)ﾟo ＼ 　ほんとは現実世界でもっとやる夫を読みたいんだお… 
　 |　　　　 （__人__）　　　　| 
　 ＼　　 　 ｀ ⌒´ 　 　 ／ 
   ```



   ```Resources/AA/aa_2.txt　
 　 　　　＿＿＿_ 
　 　　　／　　 　 　＼ 
　　　／　 _ノ 　ヽ､_　 ＼ 
　 ／ 　oﾟ⌒　　　⌒ﾟo　 ＼ 　でも現実世界は仕事で忙しくてそんな暇ないんだお･･･ 
　 |　　　　 （__人__）　　　　|　　 
　 ＼　　 　 ｀ ⌒´ 　 　 ／ 
   ```



   ```Resources/AA/aa_3.txt　
　 　 　　　＿＿＿_ 
　 　　　／⌒　　⌒＼ 
　　　／（ ●） 　（●）＼ 
　 ／::::::⌒（__人__）⌒::::: ＼ 　　だからVRでやる夫をよむお!! 
　 |　　　　　|r┬-|　　　　　| 
　 ＼ 　　 　 `ー'´ 　 　 ／   
  ```


### 8. 空のGameObjectを追加

   GameObjectを管理するための空のGameObjectを追加します

   左の Hierarchy のところで 右クリックし、 Create Empty を選択
   ![スクリーンショット 2016-08-21 22.35.59.png](https://qiita-image-store.s3.amazonaws.com/0/55219/9d522db2-ac20-08a2-f191-cc4fe070ed55.png)

   画面上には見えない、空のオブジェクトが追加されました
   名前を適当なものに変更しておきます

![スクリーンショット 2016-08-21 22.38.56.png](https://qiita-image-store.s3.amazonaws.com/0/55219/c611fc8e-369f-b4c1-5337-16f8eb05672f.png)


### 9. 追加したGameObjectに 3DText オブジェクトを追加

  先ほど追加したGameObjectの子に 3D Text を追加します

  ![スクリーンショット 2016-08-21 22.46.23.png](https://qiita-image-store.s3.amazonaws.com/0/55219/0eda8b38-375c-9e35-191b-4decea4d0e49.png)


  オブジェクトの名前, オブジェクトの位置, フォントサイズ, フォントを変更します
　TextのところにAAを貼り付け,GUIで見た目を調整しました

![スクリーンショット 2016-08-21 22.54.09.png](https://qiita-image-store.s3.amazonaws.com/0/55219/364d88f1-157f-7001-5ad6-9e0b63949251.png)
     
### 10. スクリプト追加 

   AAオブジェクトのアニメーション、次のAAの表示などを実装します

   Assetsファルダ以下にMyScriptsフォルダを作成し、そちらにスクリプトを追加します


![スクリーンショット 2016-08-21 23.05.36.png](https://qiita-image-store.s3.amazonaws.com/0/55219/04a8c9c4-4a9d-b35b-bdce-bdb666ed7bf7.png)

![スクリーンショット 2016-08-21 23.06.33.png](https://qiita-image-store.s3.amazonaws.com/0/55219/58aff2ed-0c69-9825-06a2-23721fdf5bed.png)


   作成したスクリプトをダブルクリックすると、MonoDevelop-Unity というツールが立ち上がりますのでそちらでコードを書いていきます



   ```C#:test.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class AAObjectManager : MonoBehaviour {

	private GameObject _viewAAObject = null;

	private List<TextAsset> _textAssetList;

	private int _currentPage = 0;

	private bool isFinish = true;

	// Use this for initialization
	void Start () {
		Debug.Log (Resources.LoadAll("AA",typeof(TextAsset)).Length);
		// Loading AA 
		_textAssetList = Resources.LoadAll("AA",typeof(TextAsset)).Cast<TextAsset>().ToList();

		Debug.Log (_textAssetList);

		// Binding GameObject to variable
		_viewAA     = transform.FindChild ("ViewAA").gameObject;

	}

	private int _count = 0;
	// Update is called once per frame
	void Update () {
		_count++;

		if(_count == 300 && !isFinish) {

			FadeOut ();
			_count = 0;
		}
	}

        // FadeOut
	void FadeOut(){
		Vector3 dist_pos = _viewAAObject.transform.position + (new Vector3(0,1000,0));
		Debug.Log (dist_pos);

		var moveHash = new Hashtable();
		moveHash.Add ("position", dist_pos);
		moveHash.Add ("time", 1f);
		moveHash.Add ("easeType", "easeInOutBack");
		moveHash.Add ("oncomplete", "FadeIn");
		moveHash.Add ("oncompletetarget", this.gameObject); 
		iTween.MoveTo (_viewAAObject, moveHash);

		_currentPage++;
		if (_currentPage > _textAssetList.Count) {
			isFinish = true;
		}

	}

        // FadeIn
	public void FadeIn(){
		Debug.Log ("FadeIn");

		_viewAAObject.transform.position = new Vector3 (-470, -660, 480);
		_viewAAObject.GetComponent<TextMesh> ().text = isFinish?"Fin.":_textAssetList[_currentPage].text;

		var dist = _viewAAObject.transform.position + (new Vector3 (0, 1000, 0));

		var moveHash = new Hashtable();
		moveHash.Add ("position", dist);
		moveHash.Add ("time", 1f);
		moveHash.Add ("easeType", "easeInOutBack");
		iTween.MoveTo (_viewAAObject, moveHash);


	}

	public void AAStart(){
		isFinish = false;
		_count = 0;
		_currentPage = 0;

		FadeIn ();
	}
		
}

   ```

   ~~ちょっと色々と残念...~~
   ~~コーディング力がたりない~~

   アニメーションの実装には iTween という Assetを用いました
   こちらは以下の記事を参考にさせていただきました
   参考：http://doggy.hatenablog.com/entry/2016/02/11/121327



### 11. スクリプトをオブジェクトにアタッチ

   スクリプトを作成したら、オブジェクトにアタッチします
   オブジェクトにアタッチするにはアタッチしたいオブジェクトを
   選択状態にして、画面下のエリアからドラッグ&ドロップします
   
![スクリーンショット 2016-08-21 23.19.05.png](https://qiita-image-store.s3.amazonaws.com/0/55219/9ce40f75-6a37-d220-871f-bb94f81b589e.png)

   ~~普通ドラッグって書くような~~
   
### 12. AAアニメーションスタート用のスクリプト追加

  AAのアニメーションが開始するトリガーとして
  下のパネルを見たら AAアニメーションがスタート
  としたいと思います

  今回ベースとしたデモでは床部分にパネルとボタンが設定されているので、
  こちらをつかいます

  ![スクリーンショット 2016-08-21 23.25.52.png](https://qiita-image-store.s3.amazonaws.com/0/55219/14e8753c-79dd-1c5d-719b-97c54e4dd218.png)

  一番上の Reset のオブジェクトを選択し、
  Textを変更します

  ![スクリーンショット 2016-08-21 23.27.48.png](https://qiita-image-store.s3.amazonaws.com/0/55219/82d59581-03e3-2340-954b-8a50fe419c9f.png)

  ついでに他のボタンを非表示にしておきます

  次に以下の様なスクリプトを作成します

  ```C#:AAAnimationStartScript.cs
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;

public class AAAnimationStartScript : MonoBehaviour, IPointerEnterHandler {

	private AAObjectManager _script;
	private bool _singleFlg = true;

	public void Start(){
		var go = GameObject.Find("AAObjectManager");
		_script = go.GetComponent<AAObjectManager>();

	}

	public void OnPointerEnter(PointerEventData eventData)
	{ 	
		if (_singleFlg) {
			_script.AAStart ();
			_singleFlg = false;
		}	
	}

}

  ```


  IPointerEnterHandlerを継承すると、オブジェクトにポインター(VRだと視点)が入ったときにOnPointerEnterメソッドが呼ばれます。

　OnPoiterEnterメソッドにてAAObjectManagerオブジェクトにアタッチされているスクリプトのAAStartメソッドを叩いています。
　こちらのメソッドが呼びダレることでAAのアニメーションがスタートする想定です。


　スクリプトを作成したら先ほどのボタンのオブジェクトにアタッチします。

### 13. 動作確認

  画面上部の再生ボタンをクリックし、動作確認します
  実行注は Alt + ドラッグ で視点変更できます

![aa_capture3-compressor.gif](https://qiita-image-store.s3.amazonaws.com/0/55219/fa57ed9e-36bd-113b-2900-3c4ff694cd3e.gif)

### 14. iOS向けにビルド

  iPhoneに転送するためにiOs向けにビルドします

  上部メニューから File > Build Settings を選択します

  ![スクリーンショット 2016-08-21 23.56.35.png](https://qiita-image-store.s3.amazonaws.com/0/55219/ffc7fbd7-6482-007b-3177-c91ab92eea9b.png)


  すると以下のダイアログが表示されますので iOS を選択し、Buildボタンをクリックします
![スクリーンショット 2016-08-21 23.56.46.png](https://qiita-image-store.s3.amazonaws.com/0/55219/9f74ebb8-ee02-6935-8b62-f3280ec3761a.png)

  出力先を選択するとビルドが開始されます

### 15. 実機転送

  出力先のフォルダからXcode Projectを開きます
  あとは実機を接続し、Xcode 左上から実行先をiPhoneにし、実行すれば
  iPhoneに転送されます。

　ただし実行前に Bundle Identifier の値を適当な値に変更する必要があります
  Unity からビルドするとここの値が `com.Company.ProductNames`になってますので修正します  

  ![スクリーンショット 2016-08-22 00.01.53.png](https://qiita-image-store.s3.amazonaws.com/0/55219/a10c2f4e-d0b8-a549-12e1-42711d8106a1.png)


### 16. 読む

  実機に転送されましたら、ハコスコにスマホをセッティングしVR空間でじっくりやる夫を読みます


### まとめ

  VRコンテンツの開発の敷居は高いと思っていましたが、
  Unity 未経験でもそこまで時間かからずにデモ程度まで動かすことができました。
  またOculusなどの高価なHMDがなくてもある程度はVRが楽しめることがわかり、
  とてもいい経験になりました。

  時間を見つけてもうちょっとブラッシュアップしていきたいと思います。
  ~~エタらないようにしないと~~
　　

　何か間違いのご指摘やアドバイス等いただけますと嬉しいです
  (特にスクリプトの書き方・・・)