ポケモンGOのように特定の場所に何かを表示したい場合や、Yahoo地図のように目的地までの道順をARで表示したい場合、ARとGPSを組み合わせて作るのが一般的です。
この記事ではARKitとGPSを使って京都駅の上に矢印を出すアプリケーションの作り方を紹介したいと思います。この記事の目次は次のようになります。
GPSの情報からARを表示する方法
特定の場所にARオブジェクトを表示するには、目的地の緯度経度情報を使います。と言っても緯度経度の情報をそのまま指定することはできません。
そこで現在いる場所の緯度経度と、目的地の緯度経度の差分を計算し、この差分を距離に変換します。これにより「現在地点から北に〇〇km、東に〇〇km行ったところという指定が出来るようになります。
ただ、北に〇〇と言ってもAR空間はどちらが北かという情報は持っていません。したがってARアプリ内でどちらが北かを把握して、AR空間と対応付ける必要があります。ARKitにはAlignmentというオプションがあり、これを使うと常に+z方向が北を指すようになります。
したがって、「北に〇〇km、東に〇〇km」は「+z方向にに〇〇、+x方向〇〇」と言い換えられ、無事、目的の場所にARオブジェクトを表示できる、というカラクリです。
データのインポート
まずはプロジェクトを作成し、ARKit Pluginをインポートしておきましょう。今回もUnityARKitPlugin/Examples/UnityARKitSceneを使用します。詳しい手順はこちらで紹介しています。
nn-hokuson.hatenablog.com
続いて、3Dオブジェクトをインポートします。好きなモデルをAsset Storeなどからダウンロードしてインポートしましょう。ここでは矢印の3Dモデルを表示します。(ここで使用したファイルは↓からダウンロードできます)
矢印の3Dモデルのダウンロード
ARKitの設定
上でも書いたように、AR空間の+z方向が常に北を指すようにする必要があります。そこで、AR Config OptionのAlignmentの設定を行います。
ヒエラルキーウインドウからARCameraManagerを選択し、UnityARCameraManagerスクリプトStart Alignmentを「Unity AR Alignment Gravity and Heading」に設定してください。
これによりARKitでは+z方向が北、-y方向が下(重力)方向を指すようになります。
カメラのFar Clipを設定する
また、デフォルトのカメラ設定では、Far Clipが30になっています。このままだと、30mよりも遠い場所にある物体はクリッピングされてしまいます(これ、はまった!)。そこで、カメラのFar Clipの距離は100から1000程度に設定しておきましょう。
デスクリプションの記述
また、今回のアプリはARでカメラ映像、位置測定でGPSを使うため、descriptionに記述が必要です。これがないと、アプリが落ちるので注意してください。
Build Settingsの画面でプラットフォームをiOSに変更したあとで、Player Settingsの画面から、Camera Usage DescriptionとLocation Usage Descriptionの欄に適当な文字列を設定します。
GPSの情報を取得する
それではこの矢印を京都駅の上に表示するプログラムを作っていきましょう。GPSControllerというスクリプトを作成して、次のプログラムを入力してください。
public class GPSController : MonoBehaviour
{
public double latitude = 34.984700;
public double longitude = 135.758257;
const double lat2km = 111319.491;
public Vector3 ConvertGPS2ARCoordinate(LocationInfo location)
{
double dz = (latitude - location.latitude) * lat2km;
double dx = - (longitude - location.longitude) * lat2km;
return new Vector3( (float)dx, 0, (float)dz );
}
void Start()
{
Input.location.Start();
Invoke("UpdateGPS", 1.0f);
}
public void UpdateGPS()
{
if (Input.location.isEnabledByUser)
{
if(Input.location.status == LocationServiceStatus.Running)
{
LocationInfo location = Input.location.lastData;
transform.position = ConvertGPS2ARCoordinate(location);
}
}
}
}
UnityではLocationクラスを使ってGPSの情報を取得できます。はStartメソッドの中でGPSモジュールをオンにし、Updateメソッドの中で毎フレームGPSの情報を取得しています。
最新の緯度と経度はInput.location.lastData構造体を使って得ることができます。
変数 |
データ |
latitude |
緯度 |
longitude |
経度 |
次にConvertGPS2ARCoordinateメソッドの中で、緯度経度のデータをARのワールド座標に変換しています。
まずは現在の緯度経度と、目的地の緯度経度の差分を計算します。目的地の緯度経度はGoogleMapを使うと簡単に調べられます。Google Map上で調べたい地点を右クリックし、「この場所について」を選択してください。画面下に緯度と経度が表示されます。
緯度経度の差分がわかったところで、この差分を距離(km)の情報に変換します。緯度(経度)はおおよそ1度が111319.491kmなので、これを差分の値に乗算しています。
ARKitの設定で「Unity AR Alignment Gravity and Heading」を設定したため、+z方向が北を向きます。したがって+x方向が東、-z方向が南を指します。この値に合うように、緯度に基づく差分の距離をz座標、経度に基づく差分の距離をx座標に設定します。これで、目的の場所にARオブジェクトを表示出来るようになりました。
スクリプトは矢印のオブジェクトにアタッチしておいてください。
実行結果
ビルドして実行してみましょう。実行結果は次のようになりました。ちゃんと京都駅の上(八条口ですが笑)に矢印が表示されていますね!