見出し画像

【Niantic】 Graffity ARエンタメ ハッカソン vol.6 - VPSを使った音ゲーをつくってみた【Lightship ARDK】

テーマ

我々のチームでは、Niantic Lightship ARDKを活用したゲーム制作にチャレンジしました。

今回作ったゲームは、「Sound Surf」です!

詳しい説明の前に、まずはプレイ動画をどうぞ!

コンセプト

Sound Surfは、最近リリースされたVPS機能を活かした体験を目指しました。

具体的な体験コンセプトは以下の2つです。

- 街を歩いて新しい音楽に出会う
- 音楽に合わせて身体を動かして楽しむ

1. 街を歩いて新しい音楽に出会う

Sound Surfでは、音ゲーにおけるステージの役割である楽曲が、VPSを活用して場所に紐づいています。
渋谷のハチ公前でプレイできる楽曲と、109前でプレイできる楽曲が異なる、と考えていただくとイメージしやすいかと思います。

街を散策することで新たな音楽に出会える体験を作ることで、プレイヤーの皆さんに探索の楽しみを提供しようという狙いです。

2. 音楽に合わせて身体を動かして楽しむ

AR体験の特徴は身体性による遊びの拡張にあると考えています。

音楽の持つ、思わずリズムに合わせて身体を動かしてしまう体験を、そのまま音ゲーの操作に落とし込むことで、音の波に乗る気持ちよさをつくりました。

Niantic Lightship ARDKで出来ること

ARDKでは、大きく分けて4つの機能があります。

今回のデモでは、前述の通りVPS機能をメインで使いました。

1. VPS
2. 3Dメッシング
3. セマンティックセグメンテーション
4. マルチプレイ

実装で大変だったところ

1.使える場所について
 LightShip ARDKのVPSは、基本的にNiantic Wayspotsと呼ばれる場所(Nianticが管理するVPSポイント、ポケモンGoのポケストップのイメージです)でのみコンテンツを実行する事ができます。

そのため、この場所(会場)でコンテンツを実行する!という使い方には向いていません。予めWaySpotで行う前提ならLightShipでコンテンツ作成イベント会場などで使う場合は(おそらくWaySpotが無いので)Immersalを使う、といった棲み分けが必要だと感じました。

WaySpotで体験するコンテンツを作る場合は、Immersalのような点群を作成する必要が無いのですぐにコンテンツ作成に取り組めます。これはLighShipの利点だなと感じました!

今回はLightShipの検証を行いたかったこともあり、開発者用のプライベートWayspots(好きな場所をWayspotsにできる)を利用しました。こちらはImmersalのように点群を自分で作成しアプリで使うことが出来ます。

2. 開発用のプライベートWaySpotを作成した際、サーバ側の処理時間がかかる
プライベートWaySpotを作成する際、専用アプリで作成&アップロードを行うのですが、Niantic側のサーバーでの処理時間が30分〜1時間前後かかるため、ハッカソンのような限られた時間の開発では動作確認のイテレーション回数が少なくなってしまうという問題がありました。

また、アップロード可能な点群数に制限がある(10個 / 週)のでその点も気をつける必要があります。
ここは処理時間の向上とアップロード上限の緩和を期待したいですね!

3. コンテンツの位置調整をする際に工夫が必要
ImmersalなどのVPS SDKでは『点群データをUnityのアセットとして登録してデータをUnityEditor上で表示してコンテンツの位置を調整』、といったアプローチが取れるのですが、LightShipでは基本的にUnityプロジェクト側で点群データを持たない作りになっているため、コンテンツの位置調整を行う場合工夫が必要でした。

LightShipでのコンテンツ配置のプロセスは以下の通りです。

1. UpdateメソッドなどでVPSのローカライズステータスをチェック
2. ローカライズが完了したらWayspotAnchorServiceRestoreWayspotAnchors関数にWayspotAnchorPayloadと呼ばれるコンテンツの位置情報(WayPointAnchorと呼ばれる)を持ったクラスの配列を渡すことで、VPSコンテンツ上の位置を取得
3. その後、入手できたアンカー情報をforなどで回しながらUnityのコンテンツの生成などを行うことでアンカーの位置にコンテンツを配置

コードのイメージとしてはこのような感じです

//----中略----
//ローカライズ完了したら
if (m_wayspotAnchorService.LocalizationState == LocalizationState.Localized)
{
		//アンカー情報を復元
    var _anchors =  m_wayspotAnchorService.RestoreWayspotAnchors(m_payloads);
     
    foreach (var wayspotAnchor in _anchors)
    {
					//既に生成されている場合はスキップ
        if (m_wayspotAnchorGameObjects.ContainsKey(wayspotAnchor.ID))
        {
            continue;
        }
				//このアンカーのトラッキング状態が変わった時のイベントを購読する
        wayspotAnchor.TrackingStateUpdated += TrackingStateUpdated;
        var id = wayspotAnchor.ID;
        var _go = new GameObject(); 
        Instantiate(_anchorPrefab,_go.transform);
        //---中略 コンテンツの生成----
        _go.SetActive(false);
        _go.name = $"Anchor {id}";
				//作成済みとして保存
        m_wayspotAnchorGameObjects.Add(id, _go);

}

//----中略-----

//アンカーのトラッキング状態が変わったら呼ばれるよ
private void TrackingStateUpdated(WayspotAnchorResolvedArgs args)
{
		//位置情報更新など
   var anchor = m_wayspotAnchorGameObjects[args.ID].transform;
   anchor.position = args.Position;
   anchor.rotation = args.Rotation;
   anchor.gameObject.SetActive(true);
}

実際にコンテンツを配置するためのアンカーの位置情報をコード上で取得するためには、以下の手順を踏む必要があります。

アンカー情報はWayspotAnchorPayloadというデータに入っていると↑でお伝えしましたが、そのWaySpotAnchorPayloadというのは元は文字列データです。その文字列データを用意し、アプリ実行時にデシリアライズをかけることで情報をアプリ内で取得しています。

先程のコードのStartメソッドではこのような処理を行っています。

//文字列データをUnity上で入れてる
[SerializeField] private string[] wayPoints = null;
private WayspotAnchorPayload[] m_payloads = null;

private void Start()
{
 ARSessionFactory.SessionInitialized += Initialized;
	//payload配列を作成
 m_payloads = new WayspotAnchorPayload[wayPoints.Length];

	//forで回して文字列からクラスへデシリアライズ
 for (var _i = 0; _i < wayPoints.Length; ++_i)
 {
     m_payloads[_i] = WayspotAnchorPayload.Deserialize(wayPoints[_i]);
 }
}

文字列データはBase64な文字列になっています。これをWayspotAnchorPayload.Deserializeメソッドが内部でbyte配列に変化し、クラスを生成し返却しています。

この文字列を取得するためには追加で実装が必要になってしまいます。 今回はARDKのサンプルの実装を変更することで対応しました。

サンプルスクリプトのWayspotAnchorExampleManagerの中のPlaceAnchor 関数で「タップした場所にアンカーを配置する」という処理が行われているのですが、この中で実行しているCreateWayspotAnchors関数はNianticのサーバーと通信し、アンカーを作成しています。成功するとレスポンスにアンカー情報が入っているというわけです。

そのため、サンプルを改造し、このレスポンスに入っているアンカー情報文字列を端末上にコピーする用にすることで文字列を取得するようにしました。CreateAnchorGameObjects 関数をこのように変更しました。

private void CreateAnchorGameObjects(IWayspotAnchor[] wayspotAnchors)
{
     //コピー用StringBuilder
     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.Serialize());
}

この状態でサンプルシーンをビルドし、VPSが有効な状態でコンテンツを出したい位置をタップすることで端末のコピペ領域に位置情報の文字列が入ってくる という訳です。

あとは入手した文字列を開発しているプロジェクトの中で使えば意図した位置にオブジェクトを配置することが出来ます。

コンテンツの配置を調整する際は上記のような工夫が必要でした。

ここは公式でサポートツール等あると嬉しいなと感じました。今後に期待したいです!

開発時の工夫・得られた知見

今回のハッカソンでは、大きく3つの知見を得ることができました。

1. Niantic Lightship ARDKの設計思想
Lightship ARDKは、類似のVPS SDKであるImmersalと比較して、設計思想に異なる部分があることがわかりました。

ImmersalがVPSの各マップデータを個別に保存・管理しているのに対して、Lightshipは全てのマップを一律で管理しています。

位置情報をもとに近くにあるWaySpotをアクティブにし、ローカライズを行う というケースを想定しており、そのためのAPIも提供されています。
https://lightship.dev/docs/ardk/vps/vps_getting_started.html

この機能によって、複数の場所での体験をシームレスに作ることができる利点があります。

さらに、VPS上のマップ座標を一意な文字列で管理しているため、サーバー上で文字列を管理することでコンテンツの表示位置を後から変更することができるのではと考えています(要検証ですが。。)

このように、Lightship ARDKはARクラウドが一般的に普及した未来を意識した設計思想に基づいていることがわかりました。

ちなみに、これは設計思想とは別の論点ですが、ARDKではMapの作成にLIDARを使うことができるため、非常にスキャン作業が快適でした。

2. 体験を作る上での、画面操作と身体操作のバランス
音に乗るコンセプトを実現する上で、ユーザーの画面上の操作を極力シンプルにすることで、身体を動かしながらでも楽しむことができる体験にできました。

このポイントは、Leap Triggerでも意識した部分ですが、やはり身体を使ったARエンタメ体験を設計する上で非常に重要なポイントであると再確認しました。

3. 開発ルールをちゃんと決めてから実装する
今回のチームは4人中2人がUnity初挑戦という状態でした。
そのため、経験者のエンジニアの負荷を極力減らすために、開発に着手する前にコンフリクトが発生しないような開発ルールをしっかり決めました。
結果として、開発中のコンフリクトは1件も起きなかったため、うまく機能したかなと思います。

画像1

最後に

今回、4人中2人がUnity初挑戦ということで、非常にチャレンジングなハッカソンでした。
(最後時間が足りずにできなかったのですが、もう少し時間をかけてステージのバランス調整を行いたかったのが本音です。。。笑)

最終的にはARやVPSの機能を活用したユーザーの心が動く体験を作ることができたのかなと思っています。

・・・

Graffityでは、このようなARの技術を活かし「最短3か月で“心を動かす”ARエンタメ」をコンセプトに、AR技術に特化したエンタメの企画・開発と、DX化を支援するスタジオ「Graffity AR Studio」を運営しております。

これまで累計23万ダウンロードを突破したARシューティングバトル「ペチャバト」や、グローバルに展開しているARシューティングバトル「Leap Trigger」など、ARゲームを開発・運営しており、これらの知見を活かし、スピード感を持ってARを活用した“心動かす”エンタメの企画から運用までを、ワンストップでサポートいたします。

スピード感を持って仮説検証を通してAR体験をブラッシュアップしたい企業様はぜひ「Graffity AR Studio」へお問い合わせください。


また、ARエンタメのユースケースを一緒に作りたい仲間も募集しています!


この記事が気に入ったらサポートをしてみませんか?