BioErrorLog Tech Blog

試行錯誤の記録

Unityで位置情報(緯度/経度/高度)を取得する | Android / iOSアプリ

UnityでGPS位置情報(緯度/経度/高度)を取得する方法を整理します。


はじめに

こんにちは、@bioerrorlogです。

ふと、位置情報を利用したアプリを作ってみたいと思い立ちました。

今回はその第一歩目として、Unityを用いて位置情報を取得する方法を整理します。


Unityバージョン:
2019.4.13.f1 LTS

Unityで位置情報を取得する

最終的なアプリ

最終的なUnityプロジェクトのソースコードは以下に置いています。

github.com

以下のように、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}";
    }
}

詳しくは、以下ソースプロジェクトを参照ください。

github.com

おわりに

今回は、Unityを用いて位置情報の取得方法の備忘録を書きました。

スマホ端末のGPS位置情報機能をこのように手軽に利用できるのは、Unityの強いところだと感じます。 (Godot Engineでは位置情報にアクセスする機能はまだ提供されていないようです)

この機能を使って、なにか位置情報アプリでも作れたらと思っています。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

Unity - Scripting API: LocationService

Unity - Scripting API: LocationInfo

Unity - Manual: Coroutines

Unity Mobile GPS - Real World Location - Unity 3D [Tutorial] - YouTube

Unityのゲーム画面を動画出力する

Unity Recorderを用いて、Unityゲームプレイ画面を動画出力する方法を整理します。


はじめに

こんにちは、@bioerrorlogです。

Unityで作成したゲームプレイ画面を動画に出力してみたくなりました。

最近Unityをはじめて触ってみたのですが、せっかくならコードだけでなくゲームシーンの再生動画も記録として残しておきたいなーと思ったからです。

今回は、Unity Recorderのインポートから、動画を出力するまでの方法を備忘録として残します。

作業環境

Unityバージョン:
2019.4.13.f1 LTS

OSはWindows10上で作業しています。

>ver
Microsoft Windows [Version 10.0.18363.900]

Unityのゲーム画面を動画出力する

Unity Recorderのインポート

以前はAsset Storeからインポートできたようですが、今はもうこちらからはインポートできません。

Unfortunately, Unity Recorder is no longer available.

代わりに、Package Managerから以下の手順でインポートします。

  1. ツールバーから Window > Package Manager を選択
  2. Package Managerウィンドウから Advanced > Show preview packages を選択
  3. 確認ウィンドウで Yes を選択
  4. Package Managerウィンドウから Unity Recorder を選択
  5. Install ボタンを押下

Package ManagerからUnity Recorderをインストール

Unity Recorderの設定

それでは、Unity Recorderを使ってゲームプレイ画面を動画出力します。

まず、以下の手順でRecorder Windowを表示します。

ツールバー: Window > General > Recorder > Recorder Window

Recorder Window

次に、Movie Recorderを追加し、各種設定を行います。

  • Recorderの追加:
    • + Add New Recorders > Movie
  • 設定:
    • Format: MP4
    • FIle Name: ファイル名の重複を避けるため、Wildcardsを設定する
    • Take Number: 1
    • Capture: Game View
    • Output Resolution: 任意
    • Capture Audio: 任意
    • Quality: 任意

Recorderの設定

ゲーム画面の録画

ここまできたら、いよいよゲーム画面を録画します。

START RECORDING を押すと録画がはじまり、STOP RECORDING で終了します。

これで、動画ファイルは設定画面のPathに指定したところに出力されています。

おわりに

以上、Unity Recorderを用いたゲーム画面の動画出力方法を簡単に記しました。

せっかくUnityを触るのであれば、目に見える動画という形で記録を残していくと、後から見返しやすそうです。

これから何かしらUnityで作っときは、動画の記録を残していこうと思います。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

Unity Recorder V1.0 User Manual | Package Manager UI website

Unity Recorder Tutorial 2019 - How To Record HD Video In Unity | YouTube