[Unity] Android/iOSで位置情報を取得する


既に Unity 位置情報 等で検索すると取得方法が出てくるが、自分向けにまとめる

Input

Input.location

LocationService

LocationService.status

status
Initializing Input.location.Start()を実行すると始めはこの状態になる
この状態ではまだ位置情報は取得できない
Running Input.location.Start()を実行して位置情報を取得出来るようになるとこの状態になる
Input.location.lastDataに取得した位置情報が適宜格納される
Stopped Input.location.Stop()を実行するとこの状態になる
(初期状態もこれっぽい)
この状態では位置情報は更新されない
Failed ユーザーがロケーションサービスへのアクセスを拒否した状態(未検証)

LocationService.isEnabledByUser

  • https://docs.unity3d.com/ja/current/ScriptReference/LocationService-isEnabledByUser.html
  • Input.location.isEnabledByUser で端末の設定でロケーション機能を有効にしているかどうかを返す
  • この値を位置情報を使用するタイミングでチェックし、 falseであれば有効にするよう促すのが良い
    • iOSの場合は、この値がfalseである場合に Input.location.Start()を実行すると設定を促すダイアログが表示される(未検証)

LocationService.lastData

LocationInfo.*
latitude 緯度
longitude 軽度
altitude 高度
horizontalAccuracy 水平方向の精度(メートル単位)
verticalAccuracy 垂直方向の精度(メートル単位)
timestamp タイムスタンプ
UTC基準で1970年1月1日の0時0分0秒からの経過秒数
  • 余談: timestampから現在の日時を出す
double timestamp = Input.location.lastData.timestamp;
DateTime datetime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timestamp).ToLocalTime();
Debug.Log(timestamp.ToString("yyyy-MM-dd HH:mm:ss"));

LocationService.Start()

  • https://docs.unity3d.com/ja/current/ScriptReference/LocationService.Start.html
  • 位置情報の取得を開始する
  • LocationService.Start() 後、直ぐに位置情報の取得は開始されない
    • initializeが走るので、LocationService.status も合わせて見ておくと良い
  • 第一引数: desiredAccuracyInMeters を指定することで指定されたAccuracy以上の位置情報が 取得されなくなる
    • (大体) 500mより高い値に設定することでGPSチップをオンにしておく必要がなくなるためバッテリー容量を節約できる(未検証)
  • 第二引数: updateDistanceInMeters を指定することで LocationService.lastData の更新が少なくなり、オーバーヘッドが軽減される(未検証)

LocationService.Stop()

  • https://docs.unity3d.com/ja/current/ScriptReference/LocationService.Stop.html
  • 位置情報の更新を停止することで更新処理分のオーバーヘッドを抑えることができ、バッテリー節約に繋がる(未検証/ベンチ取りたい)
  • ゲーム性によって Stop するべきかしないべきか決めると良さそう
    • ポケモンGO等、アクションにフックさせず、常に現在地を必要とする場合はStopさせなくて良い
    • こちネコ 等、アクションにフックして現在地を取得する場合、Stopさせた方が良さそう

SampleCode

LocationUpdater.cs
using UnityEngine;
using System.Collections;

public class LocationUpdater : MonoBehaviour
{
    public float IntervalSeconds = 1.0f;
    public LocationServiceStatus Status;
    public LocationInfo Location;

    IEnumerator Start()
    {
        while (true)
        {
            this.Status = Input.location.status;
            if (Input.location.isEnabledByUser)
            {
                switch(this.Status)
                {
                    case LocationServiceStatus.Stopped:
                        Input.location.Start();
                        break;
                    case LocationServiceStatus.Running:
                        this.Location = Input.location.lastData;
                        break;
                    default:
                        break;
                }
            }
            else
            {
                // FIXME 位置情報を有効にして!! 的なダイアログの表示処理を入れると良さそう
                Debug.Log("location is disabled by user");
            }

            // 指定した秒数後に再度判定を走らせる
            yield return new WaitForSeconds(IntervalSeconds);
        }
    }
}
  • 確認用スクリプト
LocationRenderer.cs
using UnityEngine;
using UnityEngine.UI;

public class LocationRenderer : MonoBehaviour
{
    public LocationUpdater updater;
    public Text text;

    void Update()
    {
        text.text = updater.Status.ToString()
                  + "\n" + "lat:" + updater.Location.latitude.ToString()
                  + "\n" + "lng:" + updater.Location.longitude.ToString();
    }
}
  • 以下の様な感じで位置情報の取得を確認できる