VR・AR日記その31-Lightship VPSを使ってみる(後編)
前回までのあらすじ
・Lightship VPSを使いたい。
・狙った場所にオブジェクトを出してみたい(例:忠犬ハチ公像の鼻の上)
・調べた結果、どうやらUnity上で現地のデータを見ながら何かすることはできないっぽい。
サンプルを紐解く
気を取り直してサンプルを見てみます。
VPSに関連するサンプルは3つあります。VpsCoverageExample、VpsCoverageListExample、WayspotAnchorsです。
VpsCoverageExample、VpsCoverageListExampleは最寄りのスポットを検索するサンプル。WayspotAnchorsはVPSのスポットでアンカーを設置したり復元したりするサンプルです。
今回は狙った場所に狙ったものを出すのが目標なので、WayspotAnchorsを使用します。
前記事で見ていたハッカソンの記事も参考にしながら見ていきます。
この記事では、アンカーの位置を取得→その位置にコンテンツを配置という流れで実装しているようです。
アンカーはどうやって設置するのか?というところですが、体験時に設置するか、あらかじめ現地で設置したデータを埋め込むかの2択かと思います。WayspotAnchorsにはアンカー保存と復元の機能が備わっています。
先の記事によると、保存に使用されているWayspotAnchorPayloadというクラスは文字列データということです。このデータを保存できれば、いつでも呼び出せるようになるはず…
そして端末のGPS情報を取得し、VPS体験できる範囲をある程度絞れば「特定の場所でのみ体験する」ことが可能になるはずです。
つまり、
1.あらかじめハチ公の鼻にアンカーを設置し、その情報を保存する(または体験時にアンカーを設置する)
2.体験を利用できる範囲をハチ公周辺に絞る
3.復号する(体験する)
という形で体験できそうです。Lightshipの思想と真逆をいっている気がしますが、道筋が見えてきました。
実際に作ってみる
今回はWayspotAnchorsを改造して作ってみます。
セーブ・ロード
サンプルではアンカーのセーブ・ロードはこのように書かれています。
public void SaveWayspotAnchors()
{
if (_wayspotAnchorGameObjects.Count > 0)
{
var wayspotAnchors = _wayspotAnchorService.GetAllWayspotAnchors();
var payloads = wayspotAnchors.Select(a => a.Payload);
WayspotAnchorDataUtility.SaveLocalPayloads(payloads.ToArray());
}
else
{
WayspotAnchorDataUtility.SaveLocalPayloads(Array.Empty<WayspotAnchorPayload>());
}
_statusLog.text = "Saved Wayspot Anchors.";
}
/// Loads all of the saved wayspot anchors
public void LoadWayspotAnchors()
{
if (_wayspotAnchorService.LocalizationState != LocalizationState.Localized)
{
_statusLog.text = "Must localize before loading anchors.";
return;
}
var payloads = WayspotAnchorDataUtility.LoadLocalPayloads();
if (payloads.Length > 0)
{
var wayspotAnchors = _wayspotAnchorService.RestoreWayspotAnchors(payloads);
CreateAnchorGameObjects(wayspotAnchors);
_statusLog.text = "Loaded Wayspot Anchors.";
}
else
{
_statusLog.text = "No anchors to load.";
}
}
WayspotAnchorDataUtility.SaveLocalPayloads()では PlayerPrefs.SetString(=Unityのデータ保存によく使われるやつ)を使って保存されるようです。ただし、ここで保存されたデータはそのまま使うことはできないと思われます。
また、ロードにあるCreateAnchorGameObjectsではanchorを設置するメソッドのようです。
ロードしたデータを復号して扱う
ハッカソンの記事ではCreateAnchorGameObjectsに手を加え、アンカー設置時情報をコピーしています。
コピー用StringBuilderを用意し、_sb.AppendLine(wayspotAnchor.Payload.Serialize());でコピーしていました。
StringBuilderを知らなかったのですが、ざっくり言うとstringの凄い版のようです。
とあるので、これをそのまま使うというよりは、何かの形で保存し、ここにある情報をもとに表示したいオブジェクトの位置や大きさを決めていったという感じでしょうか。
とりあえずWayspotAnchorsの「WayspotAnchorExampleManager」にブログに書いてあったものをそのまま記入してみました。
コード中のSaveStatusにはUIのテキストを入れています。
private void CreateAnchorGameObjects(IWayspotAnchor[] wayspotAnchors)
{
var _sb = new StringBuilder();
foreach (var wayspotAnchor in wayspotAnchors)
{
if (_wayspotAnchorGameObjects.ContainsKey(wayspotAnchor.ID))
{
continue;
}
wayspotAnchor.TrackingStateUpdated += HandleWayspotAnchorTrackingUpdated;
var id = wayspotAnchor.ID;
var anchor = Instantiate(_anchorPrefab);
anchor.SetActive(false);
anchor.name = $"Anchor {id}";
_wayspotAnchorGameObjects.Add(id, anchor);
//アンカー情報をSerialize(文字列化)してAppendする
_sb.AppendLine(wayspotAnchor.Payload.文字列データはBase64な文字列になっています。これをWayspotAnchorPayload.Deserializeメソッドが内部でbyte配列に変化し、クラスを生成し返却しています。());
SaveStatus.text = _sb.ToString();
}
}
アンカーを設置してみる
ビルドも完了したところで、手ごろなスポットで試してみると…(アンカー設置→Save→リセット→Loadで出ます。)
何となく位置情報とかが読める形で出るのかと思ったのですが、そうではないようです。シリアライズ化してるからそりゃそうか…
そして下記の記述を見つけました。
復号してもWayspotAnchorPayloadクラスになるようで、わかりやすい形では見られなさそうですね。
とはいえ、この文字列を保存すればアンカーの情報がゲットできるはず…これをアプリに埋め込んで参照するようにすれば、アンカーを設置する作業をしなくても(アプリを新規インストールした状態でも)、常に同じ場所に出せそうです。
アンカーに何かしらの作用をさせるには、設置するアンカー自体に色々スクリプトを混ぜる必要がありそうです。アンカー自体を見せたいオブジェクトにして、さらに何かするにはOnEnableとかで設置された際に位置情報を取得して…という感じでしょうか。
感想
GoogleのGeospatial APIは街中のARって感じで凄い分かりやすいのですが、Lightshipはどうやって使うんだろうという気がしていました。
例えば複数人でVPSを使って位置合わせをして、マルチプレイ的に使うとかの使い方は分かるのですが、その場所場所に合わせてARを出すという感じではないのかもしれない(少なくとも現時点では)と少し思います。
例えばSnapchatではロンドンでしか使えない(ほかの場所ではスキャンが必要)という欠点はあるものの、場所に合わせたARの配置が可能なようですし、Pretiaでは位置合わせをした情報をunityに取り込むことができます。
そういった使い方を考えると、Lightshipはよく分からないな…という気がしました。
試しにロードマップを見てみると、ARSessionの録画などの機能が実装中であり、将来的には地域ごとにARコンテンツを作れるようになりそうです。
いまは機能的にVPSが出来たという段階で、将来的に色々出来るようになるかもしれません。