UnityでARアプリの作り方2/4 GPSの緯度経度から地図の表示
こんにちは、Paid開発ユニット werdnaの酒井です。
第2回ARアプリの作り方です。
前回までで環境構築とビルドが出来るように進めてもらったと思いますので、今回は実際にアプリの実装を進めていきます。
UnityでARアプリの作り方1/4 環境構築+androidビルドからカメラ表示
UnityでARアプリの作り方2/4 GPSの緯度経度から地図の表示(本記事)
UnityでARアプリの作り方3/4 Google Direction APIの経路を地図に表示
UnityでARアプリの作り方4/4 磁気センサーで進行方向オブジェクトを回転
概要
本記事では「端末のGPS情報を取得し、Google Maps Static APIから取得した地図の表示」を目標とします。
具体的には下記内容を順に説明していきます。
- Google APIの登録
- 端末のGPS情報取得
- Google Maps Static APIを利用した地図表示
Google APIの利用設定
次に今回利用するGoogle APIの利用準備です。
本記事にて説明するGoogle Maps Static APIと次の記事で説明するGoogle Direction APIを利用できるようにします。
1からの説明で長くなってしまうので、設定済みの方や設定方法をご存知の方は読み飛ばしてください。
APIを利用するまでの手順
大まかにですが、下記3つの手順を実施することでAPIが利用可能になります。
1. プロジェクトの作成
2. APIの有効化
3. APIキーの作成
画面遷移が多く、分かりやすい説明が難しかったため、画像の赤枠内をクリックしていけばAPIを利用できるようにしています。
プロジェクトの作成
Googleアカウントでログイン後下記ページを開いてください。
Google Cloud PlatformのAPIライブラリページ
https://console.cloud.google.com/apis/library
- 画面上部の「プロジェクトの選択」よりプロジェクト選択モーダルを開きます。
-
作成後にライブラリページが開きます。
プロジェクト作成中だと「作成」しか画面上にないので、プロジェクト作成完了後に一度ページを更新し「選択」をクリックしてモーダルを開きます。
これでプロジェクトの作成と利用中への設定が完了です。
APIの有効化
作成したプロジェクトでAPIを利用できるように、今回利用するMaps Static API, Directions APIを有効化します。
これでAPIの有効化は完了です。
APIキーの作成
続いてAPIを利用するときに必要な「APIキー」の作成を行います。
作成後の状態だと、全てのAPIが利用可能になっているので、今回利用するMaps Static API, Directions APIの二つのみを利用できるように制限をかけます。
- API作成モーダル(↑の画像)右下の「キーを制限」もしくは、認証情報ページより作成したAPIキーをクリックして「API キーの制限と名前変更」ページを開きます。
「APIの制限」→「キーを制限」を選択し「Select APIs」より先ほど有効化した「Directions API」「Maps Static API」を選択し保存します。
これでAPIの設定は終了です。
APIの実行
ちゃんと設定できたかの確認として、Google Maps Static APIをリクエストしてみます。
このAPIは指定した住所・座標を中心としたGoogleMapのpngファイルを返すAPIです。
下記のようなURLで接続することが可能です。(${APIKey}を作成したapiキーに書き換えてください。)
https://maps.googleapis.com/maps/api/staticmap?center=%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE%E3%83%A9%E3%82%AF%E3%83%BC%E3%83%B3%E3%83%9B%E3%83%BC%E3%83%AB%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%B9&key=${APIKey}&zoom=18&size=640x640&scale=2&maptype=terrain&style=element:labels|visibility:off&style=element:terrain|invert_lightness:true
このURLでは「株式会社ラクーンホールディングス」でGoogleマップを検索した結果を表示しています。
正常に表示されない場合はエラーの文言が表示されているはずですので上の説明を再度確認しつつAPIをリクエストできるよう設定していただければと思います。
端末のGPS情報取得
Google Maps Static APIの利用のために必要なGPSの情報は下記のように取得することが出来ます。
項目 | 取得方法 |
---|---|
緯度-Latitude | Input.location.lastData.latitude |
経度-Longitude | Input.location.lastData.longitude |
高度-Altitude | Input.location.lastData.altitude |
水平方向の精度-horizontalAccuracy | Input.location.lastData.horizontalAccuracy |
垂直方向の精度-VerticalAccuracy | Input.location.lastData.verticalAccuracy |
タイムスタンプ-Timestamp | Input.location.lastData.timestamp |
今回必要なのは現在位置を表す緯度(latitude)・経度(longitude)の二つなので、まずはこの2つの値を画面上に表示出来るようにします。
Hierarchyウィンドウを右クリックしてUI→Textを追加
すると、Canvas下にTextオブジェクトとEventSystemオブジェクトが作成されます。
緯度・経度の2項目を表示するので、HierarchyウィンドウよりCanvasを右クリックしてUI→Textを追加
2つのテキストオブジェクトの名前を分かりやすいようにLatitude, Longitudeに変更しておきます。
[picture Hierarchy.Canvas]
今回は複数のテキストに書き換えを実施するので、Text二つを子に持つCanvasに対してAdd Componentでスクリプトをつけてあげます。
付けるスクリプトは下記のような内容になります。
using System;
using UnityEngine;
using UnityEngine.UI;
public class ShowGPSTest : MonoBehaviour
{
// GameObjectをメソッド外で定義することで、InspectorにてObjectを紐づけできる。
public GameObject LatitudeText = null;
public GameObject LongitudeText = null;
// Start is called before the first frame update
void Start()
{
// GPS機能の利用開始
Input.location.Start();
}
// Update is called once per frame
void Update()
{
// 紐づけたTextのオブジェクトを変数に格納
Text latitude_component = LatitudeText.GetComponent<Text>();
Text longitude_component = LongitudeText.GetComponent<Text>();
// Textオブジェクトのtext部分を取得したGPS情報の緯度・経度で上書き
latitude_component.text = Convert.ToString(Input.location.lastData.latitude);
longitude_component.text = Convert.ToString(Input.location.lastData.longitude);
}
}
追記後保存してCanvasに付与したScript部分を見ると、Latitude Text, Longitude Textという欄が作成されていると思います。
ここに先ほど作成したTextをドラッグアンドドロップしてあげることにより、それぞれが10, 11行目で定義したGemeObjectに紐づけられ、Updateメソッド内部でテキスト部分の更新が可能になります。
ビルドして端末で実行した画面は下記の通りです。
見やすさのために後ろのCanvasにつけているBackgroundCamera.csを無効化しています。
このアプリを立ち上げたまま、移動するとGPSの座標が変わっていくことが分かるかと思います。
(歩きスマホは危険なので、周囲に人がいないことを確認したうえで座標を見てみてください。)
Google Maps Static APIを利用した地図表示
取得したGPS情報より、Google Maps Static APIを実行します。
APIが利用可能か確認のために一度触れていますが、指定した住所・座標を中心としたGoogleMapのpngファイルを返すAPIです。
GPSの緯度・経度を利用して表示する場合にはURLの中に”center=緯度,経度”と入れてあげることで表示できます。
アプリ上に表示するために、APIより返ってきたpngファイルをテクスチャとしてオブジェクトに張り付けることで地図を表示します。
カメラの映像を表示したときと同様に、テクスチャ貼り付け用にPlaneを作成しAdd Componentで新しいスクリプトを作成します。
作成するScriptは下記のようになります。
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class StaticMapController : MonoBehaviour
{
//Google Maps Static API URL
// ${APIKey}を作成したapiキーに書き換えてください。
private const string STATIC_MAP_URL = "https://maps.googleapis.com/maps/api/staticmap?key=${APIKey}&zoom=15&size=640x640&scale=2&maptype=terrain&style=element:labels|visibility:off";
private int frame = 0;
// Start is called before the first frame update
void Start()
{
// 非同期処理
StartCoroutine(getStaticMap());
}
// Update is called once per frame
void Update()
{
// 5秒に一度の実行
if (frame >= 300)
{
StartCoroutine(getStaticMap());
frame = 0;
}
frame++;
}
IEnumerator getStaticMap()
{
var query = "";
// centerで取得するミニマップの中央座標を設定
query += "¢er=" + UnityWebRequest.UnEscapeURL(string.Format("{0},{1}", Input.location.lastData.latitude, Input.location.lastData.longitude));
// markersで渡した座標(=現在位置)にマーカーを立てる
query += "&markers=" + UnityWebRequest.UnEscapeURL(string.Format("{0},{1}", Input.location.lastData.latitude, Input.location.lastData.longitude));
// リクエストの定義
var req = UnityWebRequestTexture.GetTexture(STATIC_MAP_URL + query);
// リクエスト実行
yield return req.SendWebRequest();
if (req.error == null)
{
// すでに表示しているマップを更新
Destroy(GetComponent<Renderer>().material.mainTexture);
GetComponent<Renderer>().material.mainTexture = ((DownloadHandlerTexture)req.downloadHandler).texture;
}
}
}
内容はコメントに記載していますが補足です。
- Google Maps Static APIは色々なパラメータを渡すことで地図の色やお店の情報を載せるか等の指定が出来ますが、個人的に見やすいパラメータを固定値で入れています。GPSの住所以外は全部固定値で実行しています。
パラメータに渡す値をpublicで定義したオブジェクトで紐づけることで地図を変化させることもできます。(地図をタップしたときにzoom=nnという縮尺設定の数値を変更して、表示する地図の拡大・縮小を実施する等) -
Updateは毎フレーム呼び出されると上に記載した通り、UpdateでAPIを呼び出し続けると秒間60回も接続しに行くことになってしまうので、無駄なリクエストを避けるために5秒(300フレーム)に一度リクエストを送るようにしています。
-
APIの結果を取得するためにStartCoroutine()でメソッドを呼び出す形になっていますがAPI呼び出しやアニメーション等の1フレーム内で完結しない処理を実施する場合にはStartCoroutine()で呼び出し、
メソッド内で重たい処理をyield returnで投げることで、yield returnの処理が終わるまで待つ。という動きになります。
上記Scriptを反映して実行すると、現在地点を中心にしたマップの画像が表示されることを確認できるかと思います。
ここまでで本記事で説明したい地図表示は実装完了です。
次の記事では目的地の入力と、今回表示した地図に目的地までの経路を表示までを実装していきます。
UnityでARアプリの作り方3/4 Google Direction APIの経路を地図に表示