ARを始めるにあたりのメモ（Android）

##はじめに
去年（2017年）の夏前からとある大学の研究室から連絡があり、**ARについて学生へのサポートをしてほしい**という依頼があった。
結果だけで言うと、構築も制作もほとんど僕がかんでしまい、ゼミ生には悪いことをしたのだけれども、参考にした資料とハマりポイントについて振り返りをしておきたいと思っている。
あと無駄に長いので注意が必要。（あと画像なし）

* 導入
    * ハード/ソフト構成 
* 環境構築
    *  Unity/マーカーの設定(Vuforia)
    *  Androidビルド環境の構築
*  タッチイベントの取得
*  サンプルスクリプト
*  モデルのエクスポート/インポート
*  ビルドから実機へ
*  再・イベントの取得
* 馬鹿なんじゃないかって思う解決方法

##導入
まず、PCがあり、カメラが用意できること。
インターネットがあり、なおかつプリンターがあるとなお良い。
実機での確認時には、1年ぐらい前ぐらいまでの新しめのAndroid端末があると望ましい。
PCのスペックは、なんでも良いわけでなく、できればメモリがたくさんある方が望ましい。
また、制作していてわかったことだが、**当たり前なんだけどメモリがたくさんあっても仮想領域分あまりのない起動ディスクだと、ものすごく重くなるので**、起動ディスクはゆとりを持ったストレージがあることをおすすめ。

###ハードウェア構成
* PC
    * CPU 第7世代i5 (詳しくは忘れた)
    * memory 16GB
    * SSD 128GB
    * ストレージ 2TB
        * 上記のようなノートPCが現在10万そこそこで買えます。 
        * グラフィックは今回あまり気にしませんでした
    * FullHD（15.6inch） 
* ソフトウェア
    * windows10
    * Java(JDK8)
    * Unity 2017.1(途中から2017.2を使用)
    * 3DsMAX2016
    * photoshop
    * Illustrator
    * Vuforia(マーカー)
    * VisualStudio(途中からMonoDevelopを使用)
* デバイス
    * Nexus7(2012)/Android4.1.x

何って、**学校なのでソフトウェアがなにもうそれは豪華なこと**。
3DsMAXとか、ちょっと始めてみようっていう感じでは敷居高すぎるでしょう。（お値段）
まぁ、適宜あるもので代用。photoshopとIllustratorは僕の趣味。なくてもいい。GIMPでもなんでもいい。

###蛇足：なぜMacじゃないのか？
開発環境構築するにあたり、学校のPCは毎回設定が初期化されるらしく、新たにPCを購入する必要があった。（AndroidSDKやJavaのPathの設定など）
予算として、別のプロジェクトもあったため、1台あたり10万程度という中でのマシンの選定。
その段階で選定の中からMacは落ちてしまった。
誤算としては、学生さんが全員iPhoneを使用していたことで、検証端末がなかったこと。
これにより、教授のもつ古いAndroid（Nexus7）を借りることに。

##環境構築
###Unity/Vuforiaの設定
インターネットには素晴らしい記事があり、殆どはそこから汲み取って環境を構築した。
Unityは、バージョンは最新のものでいい。
https://unity3d.com/jp
また、脱線してしまうが、このあと何度もライセンスの取得などでメールアドレスを使用するので、Gmailアカウントを作成しておくか、+test@gmail のような感じで、テストアカウントを用意しておくと良い。
Unityライセンスを作成し、インストールをし、起動テストを行い、ライセンス認証をし、起動してみる。
Unityの使い方は他の記事に任せる。
起動できたら次へ。

Vuforiaは優れたARライブラリであるということらしい。
使い方は、次の記事が詳しい。
https://qiita.com/hey_cube/items/d12fa91abd6f7826dd78
と言うか上記の記事だけでほとんど完結している。
ライセンスを作って、SDKを落とし、マーカーを登録して、DBを設定して、マーカーをダウンロードする。
以上。
補足的に下記リンクも参考にした。
http://www.atmarkit.co.jp/ait/articles/1701/19/news028.html

Unityに戻ると、Vuforiaの設定を行う。
記事が詳しいが流れをざっと。
VuforiaのSDKをインポート。マーカーをインポート。
デフォルトのカメラをヒエラルキーから消し、Vuforiaのカメラをヒエラルキーに設定。マーカーもヒエラルキーに設定。
マーカーに秘密鍵を入れたりという設定をする。
以上。

###Androidビルド環境の構築
昔に比べて、特に何も難しいことがなくなってしまった。
Javaをダウンロード/インストール。（もしPathが通っていなかったら、環境変数で、Pathを通す）
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

AndroidStudioのインストール
https://developer.android.com/studio/index.html?hl=ja
ダウンロード/インストールする。
今回は、AndroidStudioを（ほぼ）使用しない。
AndroidStudioを起動し、Android SDK Manager と言うものを起動する。
そこから任意のターゲットOS分のSDKをインストールする。
以上。

Unityを再起動し、Build&Settingから、PCにデフォルトでなっているビルド先を、Androidに、SwitchPlatformする。
以下に使用した記事を貼っておく。（ビルドまでの一連の記事流れが乗っている）
https://unity3d.sakura.ne.jp/unity/android-build.html
http://indie-du.com/entry/2016/10/21/100835

##タッチイベントの取得
クリックで、オブジェクトを触りたいと思ったときに、クリックイベントをとればいいと思った。
GameObjectをクリックした際に、反応を返してやればいいとシンプルに考え、以下のようなコードを書いた。

```click.cs
private GameObject obj1;
// Use this for initialization
    void Start () {

        //例：Testsqという名前のGameObjectをobj1に格納
        obj1 = GameObject.Find("Testsq");
        //フラグを初期化
        showflag = true;
    }
void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log("click");
        }

```

以下のように編集しGameObjectにアタッチした。
見た目上はクリックできるようだったが、結果としてこれは失敗だった。
フラグを用意して、何度でもクリックできようにしたのが以下だ。
インデントがおかしいのは気にしないでほしい。

```ClickTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ClickTest : MonoBehaviour {


    //スクリプトで制御するGameObjectを用意
    private GameObject obj1;

    //オブジェクトが見えているかの判定をするフラグ
    private bool showflag;

    // Use this for initialization
    void Start () {

        //例：Testsqという名前のGameObjectをobj1に格納
        obj1 = GameObject.Find("Testsq");
        //フラグを初期化
        showflag = true;
    }
	
	// Update is called once per frame
	void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            //showflagがtureなら、表示オブジェクトを消す
            if (showflag) {
                Debug.Log("click");
                //ここでオブジェクトを消す
                obj1.SetActive(false);
                //フラグを管理
                showflag = false;
            }
            else if (showflag == false)
            {
                //オブジェクトを表示
                obj1.SetActive(true);
                //フラグを管理
                showflag = true;
            }
        }
		
	}
}
```

この試みは失敗に終わる。

##モデルのエクスポート/インポート
3DsMAXでモデリングしたものを、Unityにインポートしたときに、色が剥がれる、という問題があった。
というかこれは問題ではなく、経験値不足だったわけだが…。
学生さんが作っている3DsMAXのモデルにはきちんと色が反映されているようだったが、fbxにして、Unityに持ってくると、デフォルトのマテリアルが設定される。
おかしいなと試行錯誤していたら、単純に3DsMAXでマテリアルが設定されてなかった！**こんな単純なことで躓くなんて！**びっくりだよ。
マテリアルを設定するだけで高価なUnity向けのエクスポーターを使わずとも、普通のfbx書き出しで何ら問題はなかった。

##ビルドから実機へ
ビルドが通れば、実機でマーカーを映して確認ができる。
いろんなエラーがあったが、一番厄介だったのは、**プロジェクトの中のAssetsフォルダに.apkを書き出そうとするとエラーが起きる。**（ビルド時の書き出しデフォルト位置はここ）
これは唸って、結局Assets外に書き出すことな何にも問題はなかった。
もう一つは未だに解消されていないのだけれども、**Build&Runが出来ない。**だった。

以下のURLを見ながらAndroidのドライバをインストールをしたりして試みたが、うまくいかず、**とにかく端末が無い！と言われるだけで進展がなかった。**
apkを書き出し、インターネット越しに実機に送り、インストールを繰り返していた。
（デバッグログがほしいところまでは結局行かなかったので、一応それでも今回は問題がなかった）

上記にも記したがもう一度参考記事を貼っておく。
https://unity3d.sakura.ne.jp/unity/android-build.html
http://indie-du.com/entry/2016/10/21/100835

##再・イベントの取得
ここで困ったことに、GameObjectからのイベントが、上記のスクリプトでとれていないことが発覚した。
（画面全体のクリックイベントを取得しているらしい）
どうしたものかと考えても、Rayを使って、それが誰なのかを取得するスクリプト、というものばかりがでてきたので、**GameObjectをクリックしたいんや！！！**という欲求をうまく回答してくれた記事は実は一つだけであった。
http://sawalemounity.hatenablog.com/entry/2017/07/25/101635
これが救世主（メシア）。

この記事はすごくて、まさに発想の転換というやつで、どこからイベント発射されるのかはカメラから見てるもので定義すればええやんってやつだった。（間違ってたらごめんなさい）
この記事がなかったら、まだまだRayとともに研究室に篭っていたかもしれない。

カメラにRaycasterをくっつける。ヒエラルキーにEventSystemを作る。オブジェクトにEventTrigerを設定。使いたいコードをGameObjectにアタッチして、メソッドを設定。
以上。簡単！
しかも、カメラにRaycasterをアタッチし、ヒエラルキーにEventSystemがいるので、この作業は一回だけでいい。
すごい！
iPhoneはわかんないけど、**Androidは、PointerClickで、タップイベント取れるよ！すごいね！！**

##馬鹿なんじゃないかって思う解決方法
最後に僕が本物のエンジニアじゃないから、無理くり解決した方法を紹介する。
これはとても恥ずかしい。

* Build&Runが出来ない

これははまった。
apk書き出しして実機に持っていけばいいということに気がつくまで時間がかかったのと、なんと、**何故か原因不明で、実機側でgoogleDriveが使えない。**ということが起きていた。
メールで送信しようにも、**Gmailの添付ファイルの容量を超えてしまう。**
そこで、ああ、じゃぁ、送信ボックス見ればいいじゃないってことで、**同じアドレスでapkを送信して、送信失敗するので、その送信済みメールを見に行く。**
ということで無事apkをゲットした。こんな面倒なことしなくても解決方法いくらでもあっただろうな。

* コードを書いてもらうことが出来ない

学生さんは、コードを書けないので、コードが書けるようになる講義をしたかった。
（僕も大概酷いものだけれども）
なので**諦めたかった**。しかしながら、できるだけ自分たちで制御してるんだぜっていう気持ちが欲しかった。
ので、上記コードを、コピペして、必要な変数を再編集するという、**タップさせたいオブジェクトがあるだけ上記のようなC#のファイルが増える。**というとんでもないことをした。
**僕が本物のエンジニアだったら絶対に許していない蛮行だろう。**

##さいごに
この記事は長くなってしまったが、ARでタップして目標物がついたり消えたりするだけの簡単なアプリなら本当に簡単に作れるよってことを紹介したかった。
僕もUnityを実戦（実戦といえるのか？）は、ほぼ初めてだし、人に教えるということが非常に難しいということを知った。
ただ、いろいろなことはこういうシンプルな技術な積み重ねでできているのだと非常に勉強になったので、メモとしてここに残しておきたいともう。
あとで見て本当にくだらないことをしているなぁ、と思って、恥ずかしくなるのはまぁ、わかりきっていることなのだけれども。

VRがメチャクチャに今流行っているが（2018/1/10現在）、ARもやってみると楽しかったよ、ということです。
きっとこれから、そのへんの技術（AR/VR/MR）は境目なく、楽しくなっていくと思うので何かの参考になれば幸いです。