Magic Leap 2でLightshipを開発中
Magic Leap 2でLightship ARDKを使用することは、多くの点で、モバイルデバイス向けのARエクスペリエンスを開発することと同じです。 Magic Leap 2と標準的なスマートフォンではハードウェアが異なるため、いくつかの作業は異なる方法で行わなければならない。 このHow-Toでは、Unityプロジェクトにおける違いとその対処法について学びます。
前提条件
- このハウツーを使用する前に、他のPDFにあるMagic Leap 2 Lightshipのセットアッププロセスを完了する必要があります。
- このHow-ToのVPSセクションには、Unityプロジェクトにアタッチされた有効なLightship APIキーが必要です。 詳しくはセットアップページをご覧ください。
- この How-To のスクリプトは
ARLocationManager
と VPS Coverage API のエレメントを使用します。 再確認が必要な場合は、コードでロケーションARを使用する方法とランタイムでARロケーションのVPSカバレッジをクエリするを参照してください。
Magic Leap 2での再生
Unityエディターで事前に録画した映像を再生することで、LightshipのPlaybackシステムは、モバイルデバイスと同じようにMagic Leap 2上でARアプリケーションをシミュレートすることができる。
Magic Leap 2でAR体験をシミュレートする:
- Playback recordingを作成する前に、Magic Leap 2パッケージに含まれるプレハブ
Lightship ML Rig
をARシーンに追加します。 このプレハブには、エディタの入力プロバイダがコンピュータビジョン機能を実行するためのバイナリにデータを送信するのを助けるコンポーネントが含まれています。 - Using the API to Record Datasets](https://lightship.dev/docs/ardk/how-to/unity/create_playback_dataset/#using-the-api-to-record-datasets)の指示に従って、再生データセットを記録してください。 **Magic Leap 2で録画を使用するには、landscapeで録画する必要があります。
- UnityでLightshipトップメニューを開き、Lightship Settingsを選択します。 Playback**セクションで、Dataset Pathフィールドに録音へのパスを入力します。
- 必要なスクリプトとコンポーネントを使用してXRシーンをセットアップし、エディターでPlayを押してレコーディングしたUnityシーンを実行します。
マジック・リープ2用なりすましロケーション
VPSはローカライズ時にGPS座標を必要としなくなったが、Coverage APIは依然としてGPS座標を必要とする。 Magic Leap 2にはGPSハードウェアが搭載されていないため、Lightshipの位置情報機能の一部を利用するには、位置情報を偽装する必要がある。 ARDKにはLightshipLocationSpoof
というクラスが あり、デバイス上でロケーションサービスを開始する際に静的インスタンスとして初期化し、実行時にCoverage API機能に座標情報を渡すために使用することができる。
Magic Leap 2でGPSが利用できない場合でも、位置情報の偽装を行う場合は、位置情報サービスの利用を許可する必要があります。
ARDKを使って場所を偽装する:
- UnityでLightshipトップメニューを開き、Spoof Locationの下のEnabledボックスをチェックします。
- スクリプトの先頭で、
Niantic.Lightship.AR.Input
をインクルードし、位置データが適切に保存されていることを確認する:
// Add at the top of your script
using Input = Niantic.Lightship.AR.Input;
- メインスクリプトで、
LightshipLocationSpoof
オブジェクトを作成し、そのフィールドを使って、なりすましたいGPS座標を設定します。 (座標が浮動小数点数で入力されていることを確認してください!)
// Setting location coordinates
LightshipLocationSpoof.Instance.Latitude = 37.795668f;
LightshipLocationSpoof.Instance.Longitude = -122.393429f;
- スクリプトのこの後のどの時点でも、
Input
システムを使って座標を確認したり、変数を作成して簡単に値を渡したりすることができます:
// Location verification using the Input system
var latitude = Input.location.lastData.latitude;
var longitude = Input.location.lastData.longitude;
GPS座標が設定され、確認されたら、VPS Coverage APIで場所を照会するために使用できるはずです。 これらの値はいつでも変更できるため、異なる拠点間で素早くクエリーを行うことができる。
なりすましスクリプトの例
このスクリプト例では、GPS座標を偽装し、コードの他の部分に渡せるようにするプロセスを説明します。 これはARLocationManager
からロケーションを取り込み、どのロケーションになりすましたいかを選択する方法を提供し、次にロケーション情報をInput
システムを通してMagic Leap 2のために準備する。
クリックすると位置偽装デモスクリプトが表示されます。
// Copyright 2022-2024 Niantic.
using System.Collections.Generic;
using Niantic.Lightship.AR;
using Niantic.Lightship.AR.Loader;
using Niantic.Lightship.AR.LocationAR;
using Niantic.Lightship.AR.PersistentAnchors;
using Niantic.Lightship.AR.VpsCoverage;
using UnityEngine;
using UnityEngine.UI;
using Input = Niantic.Lightship.AR.Input;
namespace Niantic.Lightship.MagicLeap.InternalSamples
{
public class VPSLocalizationSample : MonoBehaviour
{
[SerializeField, Tooltip("The Location Manager")]
private ARLocationManager _arLocationManager;
[Header("UI")]
[SerializeField, Tooltip("The Dropdown for Persistent AR Locations")]
private Dropdown _arLocationDropdown;
[SerializeField, Tooltip("The Button to select an AR Location")]
private Button _arLocationChooseButton;
[SerializeField, Tooltip("The UI Canvas to display the AR Location Selector")]
private GameObject _arLocationUI;
[SerializeField, Tooltip("Text display for latitude and longitude")]
private Text _gpsText;
private List<ARLocation> _arLocationsDropdownItems = new List<ARLocation>();
private void OnEnable()
{
if (!LightshipSettings.Instance.UseLightshipSpoofLocation)
{
Debug.LogError
(
"Magic Leap does not provide GPS, which is necessary for Lightship VPS. " +
"Please enable the Spoof Location feature in the Lightship Settings menu in " +
"order to try out the VPS Localization Sample."
);
return;
}
_arLocationManager.locationTrackingStateChanged += OnLocationTrackingStateChanged;
if (_arLocationManager.AutoTrack)
{
_arLocationUI.SetActive(false);
}
else
{
CreateARLocationMenu();
_arLocationUI.SetActive(true);
_arLocationChooseButton.onClick.AddListener(OnLocationSelected);
}
if (Input.location.status == LocationServiceStatus.Stopped)
{
Input.location.Start();
}
UpdateGPSText();
}
private void OnDisable()
{
_arLocationManager.locationTrackingStateChanged -= OnLocationTrackingStateChanged;
_arLocationChooseButton.onClick.RemoveListener(OnLocationSelected);
}
private void CreateARLocationMenu()
{
var arLocations = _arLocationManager.ARLocations;
foreach (var arLocation in arLocations)
{
_arLocationDropdown.options.Add(new Dropdown.OptionData(arLocation.name));
_arLocationsDropdownItems.Add(arLocation);
}
if (_arLocationsDropdownItems.Count > 0)
{
_arLocationChooseButton.interactable = true;
}
}
private void OnLocationSelected()
{
var currentIndex = _arLocationDropdown.value;
var arLocation = _arLocationsDropdownItems[currentIndex];
_arLocationManager.SetARLocations(arLocation);
var gpsLocation = arLocation.GpsLocation;
LightshipLocationSpoof.Instance.Latitude = (float)gpsLocation.Latitude;
LightshipLocationSpoof.Instance.Longitude = (float)gpsLocation.Longitude;
UpdateGPSText();
_arLocationManager.StartTracking();
}
private void OnLocationTrackingStateChanged(ARLocationTrackedEventArgs args)
{
if (!args.Tracking)
{
// We de-activate the gameObject when we lose tracking.
// ARLocationManager will not de-activate it automatically
args.ARLocation.gameObject.SetActive(false);
}
}
private void UpdateGPSText()
{
// First, check if user has location service enabled
if (!Input.location.isEnabledByUser)
{
_gpsText.text = "Location service is not enabled";
return;
}
var latitude = Input.location.lastData.latitude;
var longitude = Input.location.lastData.longitude;
var altitude = Input.location.lastData.altitude;
_gpsText.text = $"Latitude: {latitude}\nLongitude: {longitude}\nAltitude: {altitude}";
}
}
}