Unity × GPS × GoogleMapsAPI で日常生活にミニマップを
ゲームをしてる時にふと、「日常生活にもミニマップあったら便利なんじゃないか?」と思ったのでUnityを使ってAndroidアプリとして実装してみました。
具体的に言うと「Webカメラを通して見る世界の左下隅に、GPSで取得した現在地の周辺のGoogleMapが常に表示され続けるAndroidアプリをUnityで作ろう」という話です。
実装の際に課題になったものは、
- UnityをAndroidでビルドできるようにする
- GPSで現在地の座標を取得する
- Android のカメラ画像を表示する
- GoogleMapsAPIで位置情報に応じたマップを表示して現在地にマーカーをたてる
の4点でした。
UnityをAndroidでビルドできるようにする方法は割愛させていただきますが、私が参考にさせていただいたサイトを載せておきます。
- Unityで作ったアプリをケーブルでAndroid実機で動かす方法 | HIROMARTBLOG
- 【スマホVR】Unity 5 PersonalとCardboard SDKで嫁をAndroidに召喚する【MMD】 #JAGVR - ReDo
ちなみに私はMinimum API Levelの設定で小一時間程悩みましたが、ここはお使いのAndroidのバージョンに合わせてください。私が使ってるバージョンは4.2.2だったのですが、なぜか4.2ではなく4.1でないと通りませんでした。
また、Virtual Reality Supportedにチェックが入ってるとMinimum API Levelが変更できないのでチェックを外すことを忘れずに。
次に、UnityでGPSを使った位置情報の取得。
これは「Unityで位置情報を取得 - チラ裏Unity」さんを参照してください。全部書かれてます。
カメラの映像を表示するには、WebCamTextureを使用します。
using UnityEngine; using System.Collections; public class WebCam : MonoBehaviour { public int Width = 1920; //解像度横 public int Height = 1080; //解像度縦 public int FPS = 20; void Start () { WebCamDevice[] devices = WebCamTexture.devices; WebCamTexture webcamTexture = new WebCamTexture(devices[0].name, Width, Height, FPS); GetComponent<Renderer> ().material.mainTexture = webcamTexture; webcamTexture.Play(); } }
このスクリプトをPlaneなりQuadなりにアタッチすればAndroidカメラからの映像を見ることができます。
UnityでGoogleMapsAPIを使うには、WWWクラスを使用します。さらに、GPSで取得した現在地と組み合わせるコードはこのようになります。
using UnityEngine; using System.Collections; public class MiniMap : MonoBehaviour { GUITexture mapGuiTexture; private float intervalTime = 0.0f; private int width = 300; private int height = 200; private double longitude; private double latitude; private int zoom = 16; void Start () { mapGuiTexture = this.GetComponent<GUITexture> (); GetPos (); GetMap(); } void Update(){ //毎フレーム読んでると処理が重くなるので、3秒毎に更新 intervalTime += Time.deltaTime; if (intervalTime >= 3.0f) { GetPos (); GetMap (); intervalTime = 0.0f; } } void GetPos () { //GPSで取得した緯度経度を変数に代入 StartCoroutine (GetGPS()); longitude = Input.location.lastData.longitude; latitude = Input.location.lastData.latitude; } void GetMap () { //マップを取得 StartCoroutine(GetStreetViewImage(latitude, longitude, zoom)); } private IEnumerator GetGPS() { if (!Input.location.isEnabledByUser) { yield break; } Input.location.Start(); int maxWait = 120; while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0) { yield return new WaitForSeconds(1); maxWait--; } if (maxWait < 1) { print("Timed out"); yield break; } if (Input.location.status == LocationServiceStatus.Failed) { print("Unable to determine device location"); yield break; } else { print("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp); } Input.location.Stop(); } private IEnumerator GetStreetViewImage(double latitude, double longitude, double zoom) { //現在地マーカーはここの「&markers」以下で編集可能 string url = "http://maps.googleapis.com/maps/api/staticmap?center=" + latitude + "," + longitude + "&zoom=" + zoom + "&size=" + width + "x" + height + "&markers=size:mid%7Ccolor:red%7C" + latitude + "," + longitude; WWW www = new WWW(url); yield return www; //マップの画像をTextureとして貼り付ける mapGuiTexture.texture = www.texture; //ミニマップに透明度を与える mapGuiTexture.color = new Color (mapGuiTexture.color.r, mapGuiTexture.color.g, mapGuiTexture.color.b, 0.4f); } }
このスクリプトをGUITextureにアタッチすればミニマップが見れるようになります。
少し(というかかなり)GPSの精度が低いのが問題ですが、これで日常生活にミニマップ機能を追加するアプリの完成です。
ハコスコみたいなやつと一緒に使用すれば日常がゲームの世界になったように感じることができるかもしれませんね。