UnityでGPS位置情報(緯度/経度/高度)を取得する方法を整理します。
はじめに
ふと、位置情報を利用したアプリを作ってみたいと思い立ちました。
今回はその第一歩目として、Unityを用いて位置情報を取得する方法を整理します。
Unityバージョン:
2019.4.13.f1 LTS
Unityで位置情報を取得する
最終的なアプリ
最終的なUnityプロジェクトのソースコードは以下に置いています。
以下のように、10秒毎にスマホ(Android / iOS)から緯度/経度/高度を取得し、画面出力するシンプルなアプリケーションです。
以下、要点を説明します。
位置情報を取得するスクリプト
位置情報を取得するC#スクリプトを以下に示します。
位置情報の取得には、UnityのLocationService機能を利用します。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Location : MonoBehaviour { public static Location Instance { set; get; } public float latitude; public float longitude; public float altitude; private void Start() { Instance = this; DontDestroyOnLoad(gameObject); StartCoroutine(StartLocationService()); } private IEnumerator StartLocationService() { // First, check if user has location service enabled if (!Input.location.isEnabledByUser) { Debug.Log("GPS not enabled"); yield break; } // Start service before querying location Input.location.Start(); // Wait until service initializes int maxWait = 20; while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0) { yield return new WaitForSeconds(1); maxWait--; } // Service didn't initialize in 20 seconds if (maxWait <= 0) { Debug.Log("Timed out"); yield break; } // Connection has failed if (Input.location.status == LocationServiceStatus.Failed) { Debug.Log("Unable to determine device location"); yield break; } // Set locational infomations while (true) { latitude = Input.location.lastData.latitude; longitude = Input.location.lastData.longitude; altitude = Input.location.lastData.altitude; yield return new WaitForSeconds(10); } } }
コードは、Unityドキュメントに記載されているサンプルコードを参考・改変したものです。
流れとしては、コルーチンの中で、
- GPSアクセス権限の確認
- LocationServiceの起動
- LocationService起動失敗時の処理
- LocationServiceから位置情報の取得
を行っています。
// First, check if user has location service enabled if (!Input.location.isEnabledByUser) { Debug.Log("GPS not enabled"); yield break; }
まず、Input.location.isEnabledByUser
を参照し、スマホの位置情報へのアクセスが許可されているかを確認します。
アクセスが許可されていない場合は、yield break;
でコルーチンを終了します。
// Start service before querying location Input.location.Start(); // Wait until service initializes int maxWait = 20; while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0) { yield return new WaitForSeconds(1); maxWait--; }
次に、Input.location.Start();
でLocationServiceを起動します。
最大で20秒間の起動時間を設け、LocationServiceの起動を待機します。
起動待機の実装としては、yield return new WaitForSeconds(1);
とすることで1秒後にコルーチンを再開させ、LocationServiceのステータスを監視させています。
// Service didn't initialize in 20 seconds if (maxWait <= 0) { Debug.Log("Timed out"); yield break; } // Connection has failed if (Input.location.status == LocationServiceStatus.Failed) { Debug.Log("Unable to determine device location"); yield break; }
次は、LocationServiceの起動に失敗した時の処理を入れています。
20秒経ってもLocationServiceが起動しなかったときmaxWait <= 0
、LocationServiceのステータスがFailedとなったときInput.location.status == LocationServiceStatus.Failed
に、それぞれコルーチンを終了させます。
// Set locational infomations while (true) { latitude = Input.location.lastData.latitude; longitude = Input.location.lastData.longitude; altitude = Input.location.lastData.altitude; yield return new WaitForSeconds(10); }
最後に、いよいよ緯度/経度/高度を取得します。
それぞれ、Input.location.lastData.
から緯度latitude
/ 経度longitude
/ 高度altitude
を取得します。
今回は数秒毎に定期で取得したかったので、whileループの中で位置情報取得毎に10秒の待機を挟んでいます。
以上で、位置情報が取得出来ました。
この位置情報を外部から参照するには、上記スクリプトで作成したクラスLocation
内で作成したInstance
を介して参照します。
例えばTextとして位置情報を表示するためには、以下のようなスクリプトを別途立てて、Location.Instance
から位置情報を参照します。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UpdateLocationText : MonoBehaviour { public Text location; private void Update() { location.text = $"緯度: {Location.Instance.latitude}\n経度: {Location.Instance.longitude}\n高度: {Location.Instance.altitude}\n\nCount: {Location.Instance.gps_count}\nMessage:\n{Location.Instance.message}"; } }
詳しくは、以下ソースプロジェクトを参照ください。
おわりに
今回は、Unityを用いて位置情報の取得方法の備忘録を書きました。
スマホ端末のGPS位置情報機能をこのように手軽に利用できるのは、Unityの強いところだと感じます。 (Godot Engineでは位置情報にアクセスする機能はまだ提供されていないようです)
この機能を使って、なにか位置情報アプリでも作れたらと思っています。
[関連記事]
参考
Unity - Scripting API: LocationService