5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Unity+ARCore】位置情報から飲食店に空席状況を表示させるには | 前編

Posted at

作ったサービス

目次
1.本記事でできること
2.動作環境
3.システム構成図
4.Unityプロジェクトの作成
5.ARCore Extensionsインストール
6.ARCoreAPIの取得方法
7.特定の位置にオブジェクトを表示させる
8.まとめ

本記事でできること

こんにちは。位置情報から飲食店に空席状況をAR空間に表示させるサービスを作ってます。前編ではUnityとARCore Geospatial APIを使い特定の位置情報のもとにARコンテンツを表示する方法を紹介します。
ARCore Geospatial APIのインストールやAPIの発行について困っている方の参考になればと思います。

動作環境

AR環境

・Unity 2022.3.49f1
・ARFoundation 5.1.5
・Google ARCore XR Plugin
・ARCore Extensions: 1.46.0

実行デバイス

Galaxy S22 SC-51C

サーバー環境

Flask フレームワーク
ngrok ローカルサーバー

システム構成図

構成図.png

Unityプロジェクトの作成

上記の環境のUnityバージョンをダウンロードします。
https://unity.com/ja/releases/editor/archive

Unity HubでAR Moibleテンプレートを使用してプロジェクトを作成します。

スクリーンショット 2024-11-08 101617.png

プロジェクトを開けたらそのまま実行します。Game ViewでAR空間をシミュレーションすることができます。実行できたらOKです。

AR Mobileテンプレートを使ってない方は最新バージョンのARFoundationとGoogle ARCore XR Pluginの導入を済ませてください。

ARCore Extensionsインストール

スクリーンショット 2024-11-08 105127.png

ARCore Extensions: 1.46.0を導入するにはWindow > Package Managerを開き左上の+ボタンを押しAdd pacake from git URL...を押します。スクリーンショット 2024-11-08 110255.png
以下のGit URLをコピーして貼り付けます。
https://github.com/google-ar/arcore-unity-extensions.git#arf5

XROriginが割り当てられない方
最新のバージョンだとXROriginがスクリプトに参照できないため上記のURLでインストールしてください。
XROriginを参照できない方はサンプルシーンをAssetsフォルダーから直接削除してインポートし直すと参照できるようになります。

sampleシーン.png

最新バージョンがインストールされてることを確認したらGeospatial Sampleをインポートします。
スクリーンショット 2024-11-08 114452.png
AssetsからARCore ExtensionsのScenesからGeospatialArf5シーンを開きます。

Xrorigin.png

AR Core ExtensionsにXR Originが入っているか確認してください。入っていれば次はARCore APIの取得に移ります。実行してもまだエラーが出る状態なので実行できないはずです。

ARCore APIの取得方法

必要なもの

クレジットカード、Googleアカウント
ARCore Geospatial APIを機能させるためのAPIをGCP (Google Cloud Platform) で 発行し取得します。登録にはクレジットカード情報が必要ですが無料の範囲でも使うことができます。
無料で使える範囲を超えるリクエスト数はそれに応じて料金が発生します。
※個人の責任でお願いします。

Google Cloudに登録

URLにアクセス
https://console.cloud.google.com/apis/library/arcore
スクリーンショット 2024-11-08 141103.png
無料で利用開始>Googleアカウントにログイン>クレジットカード情報を入力
確認コードをメールで受け取り入力します。Google CloudへようこそというメールがきたらGoogle Cloudを利用できます。
再度上記のURLへアクセスしARCore APIを有効にします。
プロジェクトは適宜作ってください。

ARCore APIの発行

スクリーンショット 2024-11-08 143605.png
有効にしたら管理画面が表示されるのでAPIとサービスの認証画面という文字をクリックしてください。スクリーンショット 2024-11-08 143616.png
認証情報を作成をクリックしAPIキーを選択します。しばらく待つとAPIキーが作成できるのでAPIキーをコピーしてください。

APIキーの取り扱いには注意してください。

デモをビルド

スクリーンショット 2024-11-08 144552.png

取得したAPIキーをUnityに渡す

Edit>Project Settings>XR Plug-in Management>ARCore Extensionsから上記のような設定にしてください。※iOSでビルドしたい方はiOSサポートにチェックをいれて同様にAPIキーをいれてください。

APIキーを入れまだProject Settings閉じずに
スクリーンショット 2024-11-08 145308.png
PlayerからビルドするプラットフォームのActive Input HandlingBothにします。
(AndroidだとBothにすることを求められる。なぜかはわからない。)
BothにしたらUnityが再起動するので待ちます。

スクリーンショット 2024-11-08 155414.png

ビルドする前にGeospatial ModeをEnableにします。

スクリーンショット 2024-11-08 150054.png
では実際にシーンをScene In Buildに追加しビルドしてみます。

デモを実行

Screenshot_20241108_150650_TEST.jpg

いろいろな数値がでてきた。一番上から緯度と経度、高度もあります。Accuracyに関してはこの次で重要なものになります。

特定の位置にオブジェクトを表示させる

特定の位置にオブジェクトを表示するために、ARCore Geospatial APIを使う際の簡単な手順について説明します。

1. Geospatial APIと屋外での使用について
まず、ARCore Geospatial APIはGPSやVPS(Visual Positioning System)を利用して正確な位置情報を取得しますが、屋内ではうまく機能しません。そのため、基本的に屋外での使用をおすすめします。

2. ローカライズのチェック
実際にオブジェクトを表示する前に、位置情報がどれだけ正確かを確認する「ローカライズチェック」を行います。このチェックでは「Accuracy(精度)」の値を確認します。Accuracyの値が低いほど、位置情報が正確であることを意味します。

3. スクリプトの概要
スクリプトを作成し、Accuracyの値が一定のしきい値以下になるまで待機します。しきい値を下回った場合、位置情報の精度が十分に確保されたと判断します。

using Google.XR.ARCoreExtensions;
using System;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;


public class LocalizeCheck : MonoBehaviour
{
    // しきい値を設定する(方位角の許容誤差)
    public double orientationYawAccuracyThreshold = 16;
    // しきい値を設定する(水平精度の許容誤差)
    public double horizontalAccuracyThreshold = 14;

    // ローカライズが完了したときに実行するアクション
    public Action OnFinishedLocalization { get; set; }
    // ローカライズが失われたときに実行するアクション
    public Action OnLostLocalization { get; set; }

    [SerializeField] private AREarthManager earthManager;

    private bool isLocalizing;

    private bool hasLostLocalization = false;

    void Update()
    {

        bool currentlyLocalizing = IsLocalizing();

        if (currentlyLocalizing && !hasLostLocalization)
        {
            hasLostLocalization = true;
            OnLostLocalization?.Invoke(); // イベントを呼び出す
        }

        else if (!currentlyLocalizing && hasLostLocalization)
        {
            hasLostLocalization = false; 
            OnFinishedLocalization?.Invoke(); // イベントを呼び出す
        }
    }

    // ローカライズ状態を判定するメソッド
    bool IsLocalizing()
    {
        // ARセッションと位置情報サービスが正常に動作しているか確認
        bool isSessionReady = ARSession.state == ARSessionState.SessionTracking &&
                              Input.location.status == LocationServiceStatus.Running;
        // 現在のARトラッキング状態を取得
        var earthTrackingState = earthManager.EarthTrackingState;

        // 地理的なポーズを取得(トラッキング中の場合のみ)
        var pose = earthTrackingState == TrackingState.Tracking ?
            earthManager.CameraGeospatialPose : new GeospatialPose();

        // ローカリゼーションの状態を判定し、しきい値を超えている場合はローカリゼーションが不安定と判断
        return !isSessionReady ||
               earthTrackingState != TrackingState.Tracking ||
               pose.OrientationYawAccuracy > orientationYawAccuracyThreshold ||
               pose.HorizontalAccuracy > horizontalAccuracyThreshold;
    }
}

スクリーンショット 2024-11-08 162600.png

using Google.XR.ARCoreExtensions;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;

public class SampleSpawnObject : MonoBehaviour
{
    public double TestLatitude; //出現させたい緯度を入力
    public double TestLongitud; //出現させたい経度を入力
    private LocationInfo currentLocation;
    private LocationServiceStatus Status;
    [SerializeField] LocalizeCheck localizeCheck;
    public GameObject Prefab;//出現させたいプレファブ
    public ARAnchorManager anchorManager;
    public AREarthManager earthManager;
    GameObject instance;
    ARGeospatialAnchor anchor;

    void Start()
    {
        localizeCheck.OnFinishedLocalization += SpawnObject;
        localizeCheck.OnLostLocalization += DestroyObject;
    }

    private void SpawnObject()
    {
        var pose = earthManager.CameraGeospatialPose;
        double targetAltitude = pose.Altitude + 1.5;
        var anchor = anchorManager.AddAnchor(
            TestLatitude,
            TestLongitud,
            targetAltitude,
            Quaternion.identity
        );

        instance = Instantiate(Prefab, anchor.transform);
    }

    private void DestroyObject()
    {
        if (instance != null)
        {
            Destroy(instance);
            instance = null;
        }
        if (anchor != null)
        {
            Destroy(anchor);
            anchor = null;
        }
    }
}

スクリーンショット 2024-11-08 165015.png
オブジェクトを表示させたい場所の緯度と経度をGoogle Mapからとってきてインスペクター上で貼り付けます。先ほどと同様のシーンをBuild&Runで実行。

実行

Screenshot_20241108_173458_TEST.jpg

まとめ

VPSの中でGeospatial APIはかなり使いやすいと思います。スキャンしなくてもいいというのが最大の利点です。後編ではサーバーから飲食店の空席状況を取得して飲食店の位置に表示させたいと思います。
お読み頂き誠に有難うございました。

参考

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?