[Unity] GO Mapアセットを使ってみる

## GO Mapアセットとは

![gomap.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/04d2dcf1-62a7-e4ff-2200-e9629bda3177.gif)

- [GO Map - 3D Map for AR Gaming](https://www.assetstore.unity3d.com/jp/#!/content/68889)

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">PokemonGO的なもの、あっと言う間にできたー。<br>Asset Storeにそのままの「GO Map」というアセットを使えば簡単にできたw<a href="https://t.co/bqXkUGK6Zg">https://t.co/bqXkUGK6Zg</a><br>ゲーム会社の上司にこれをみせてはいけないw <a href="https://t.co/GoOfJjVfJv">pic.twitter.com/GoOfJjVfJv</a></p>&mdash; 伊藤周 (@warapuri) <a href="https://twitter.com/warapuri/status/774121286394011648">2016年9月9日</a></blockquote>

- Unity伊藤さん(現在サバティカル中！)のツイートで話題になったアセット
- APIから地理情報を引っ張ってきてパースして3Dモデルを展開してオマケでカメラの操作周りのソースも付いて、まさに何とかGOlikeなゲームの実装をアシストしてくれるアセット
- 実装の深い部分に触れない範囲でざっくり使い方を書いてみる

## 簡単な使い方
- `3D Demo scene` を開くことでこのアセットを使う上で必要な全てを見ることが出来るはず
- ネットワーク繋いだ状態で実行することでマップの取得/生成が行われる
  - 描画される場所はUnityEditor上であれば`LocationManager`の`DemoLocation`で定義された場所
- このままビルドしてAndroid/iOS端末上で見れば、現在位置周辺のマップの取得/生成が行われる
  - 移動して位置情報の更新が行われると追加でマップの更新(および遠くのマップの破棄)が行われる

![3ddemo.png](https://qiita-image-store.s3.amazonaws.com/0/102664/cf4a91e8-83f3-9be1-ae22-502187608004.png)

## 主に使用するScript
### LocationManager
- Demo上では `LocationManager` GameObjectにアタッチされている
- Android/iOS等の位置情報が取得できる端末においては現在の座標を取得し、定期的に更新する
  - `UseLocationService` を `false` にすることで恣意的に現在の位置情報を利用させなくもできる
- UnityEditor等の位置情報が取得できない端末においては `DemoLocation`で定義された場所の座標を使用する
  - 任意の座標を表示する場合には `DemoLocation` を `Custom` にした上で `demo_CenterWorldCoordinates` に座標を設定する
- `onLocationChanged` イベントが用意されているので、位置情報の更新時、更新後の座標を利用した任意のコールバックを起こすことが可能
  - サンプルシーン内の `MoveAvatar` の実装を参考にすると良さそう

![locationmanager.png](https://qiita-image-store.s3.amazonaws.com/0/102664/21160713-f80d-ef6a-061a-2a555a73dbf7.png)

### Map
- Demo上では `Map` GameObjectにアタッチされている
- 位置情報の更新にフックして、SmartTileを構築/破棄する君
  - 現在の座標のzoomレベルに基き、近隣のSmartTileを生成する
  - タイルとして生成済みだが、近隣のSmartTileに含まれないものは破棄する
- 都度更新してほしくない場合は `DynamicLoad` を false にすると良い
- `Layers` にて建物や水面に適応するMaterial等を設定することが可能
  - MapZen vector maps APIで設定できるLayerなら追加で描画することも可能
  - また `RenderingOption` にて kind (種別) によっても細かく高さなどの調整も可能
  - 詳しくは https://mapzen.com/documentation/vector-tiles/layers/#layer-reference

![map.png](https://qiita-image-store.s3.amazonaws.com/0/102664/22662f8d-846e-3834-d0fe-ac995140ab78.png)

### (SmartTile)
- Mapによって動的に生成される
- APIを叩き、jsonをパースし、地理情報に紐付いてオブジェクトを生成する実装はここに含まれている

###  TwoXOrbitGesture
- Demo上では `MainCamaera` GameObjectにアタッチされている
- Camaraにアタッチすることで、入力によるカメラ操作を行ってくれる君
- ドラッグによるカメラを旋回させることができる
- ピンチイン/アウト (モバイル端末でない場合はマウススクロール) で俯瞰したような視線とプレイヤーの一人称のような視線を徐々に切り替えることが出来る
- 町中に入り込むようなFPSのようなゲームを作る場合は逆にこれは使わないようにすると良さそう

![camera.png](https://qiita-image-store.s3.amazonaws.com/0/102664/dcc696c3-a289-72dc-bec1-3d3a160fe956.png)

## API(データソース)

![mapzen.png](https://qiita-image-store.s3.amazonaws.com/0/102664/e155ae6d-85d8-6c09-48b8-1d2d9ad7113f.png)


- MapZen vector maps API を使用している
  - https://mapzen.com/projects/vector-tiles/
  - https://mapzen.com/documentation/vector-tiles/
- APIによってどういう結果が返ってくるか
  - [Json Parser Online](http://json.parser.online.fr/) に http://vector.mapzen.com/osm/buildings,landuse,water,roads/17/70080/46912.json この結果を突っ込むと見やすい
  - 指定したlayer群を対象にzoomレベルと座標を元に地理情報を返している
  - 具体的には建物のポリゴンを構築するための座標や建物の種別、どのzoomレベルで描画しているか等
- MapZen vector maps API ではOpenStreetMap等のオープンソースデータを利用している
  - https://mapzen.com/documentation/vector-tiles/data-sources/
  - https://mapzen.com/documentation/vector-tiles/attribution/ (リリース時はアトリビューションも注意)
- 現状はAPIKeyを設定しなくても特に制限なく使用することが出来る
  - 将来的に使用回数/ライセンス的に制約掛かることもありそうなので登録したほうが無難な雰囲気
  - APIキーはMapコンポーネントにて指定可能
  - https://mapzen.com/documentation/vector-tiles/api-keys-and-rate-limits/

## 最後に
- Unityで位置情報ゲーム作る場合には、この実装見るだけで勉強になること多いので$20の価値あると思う...!!