拡張音楽プレイヤーを作ってみました

## 経緯
自分はARグラスが普及した未来の日常を想像するのが好きです。過去には音楽プレイヤー・携帯電話・ネット通信機器を一台にまとめたiPhoneが日常を変えました。同様に、ARグラスが広まった際にも日常的に使われるアプリが登場し、生活を大きく変えるはずです。

そこで、ARグラスの普及期に使われるような、他が取り組まない個人開発ならではの日常的なARアプリを作ろうと思いました。まずは一歩目として、音楽をARで楽しめる新しい音楽プレイヤーを開発することにしました。

## コンセプトの整理
音楽の聞き方を雑に2軸で分けるなら、同期的or非同期的の軸と、場所に依存or場所を問わないの軸に分けられると思います。

![音楽分類.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182279/3f50eb9e-b5e1-4445-8d18-67657e39f59d.png)

非同期的で場所を問わない聴き方ならSpotifyなど、すでに充実しています。

一方、非同期的で場所に依存する音楽の聴き方はまだ開拓の余地が大きい領域だと思っています。例えば、休日に街を散策しているとき、「あの場所に行けば特別な音楽とAR演出が楽しめる」といった体験を作れないかと考えました。

また、音楽再生にとどまらず、視覚的にも音楽を楽しめるようなARを提供出来るようにしたいと考えました。具体的には、VFX Graphを用いて演出出来るようにしています。

さらに、この仕組みを誰もが簡単に作って投稿できるプラットフォームに発展させられれば、もっと面白くなると感じています。最終的には、街中の各所でその場所限定の音楽AR体験が楽しめる日常を作りたいと考えています。

## 今回作ったものの概要
Unity Editor上で制作した音楽とVFXをアセットバンドル形式でアプリに配信し、特定の場所での音楽AR体験が出来るようにする仕組みを作りました。

また、アプリ側でImmersal SDKを用いたVPS（Visual Positioning System）による位置合わせを行い、正確な位置でコンテンツを再生できるようにしています。

この仕組みにより、ユーザーは現実の特定の場所でのみ音楽とVFXを楽しめるようになっています。

<iframe width="560" height="315" src="https://www.youtube.com/embed/Kx6tjdLqDTQ?si=k2N9wL2QVbrHjjc5" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## リポジトリ
参考情報としてリポジトリを公開します。今はまだ製品版には程遠いので悪しからず。
クローズな環境で現状よりずっと良いものを作るつもりです。
Lichtアプリ, Licht Authoring(Editor拡張)が同封されています。
https://github.com/TomohiroHibino600/LichtProject

## 使用手順
1 アプリを使い、音楽を体験する場所の環境情報(マップ)をImmersal SDKの処理でスキャンします。
<iframe width="560" height="315" src="https://www.youtube.com/embed/oHIHgqhgWP0?si=qqSuNvLPfLkmdG4X" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

2 音楽ファイルをFirebaseにアップロードします。※収録機能に変えるかもしれません。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182279/e306b72f-cbb1-41c4-85bc-86619126b338.png" width="200">

3 オーサリングツール(Editor拡張)でスキャン済みのマップ上に、音楽に合わせて動くなどのVFXを制作します。
<iframe width="560" height="315" src="https://www.youtube.com/embed/rZVqU9WzMM4?si=qurxLulT3tOKw7u5" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

4 完成したコンテンツをAssetBundleとしてFirebase Storageにアップロードし、Firestoreに配置情報などのメタデータを保存します。
<iframe width="560" height="315" src="https://www.youtube.com/embed/_SLm6xP2uRU?si=liNvcIgPG5v4cUCm" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

5 ユーザーは現地でVPS解決した後、AssetBundleをダウンロードしてその場所限定の音楽とVFXエフェクトを楽しむことができます。
<iframe width="560" height="315" src="https://www.youtube.com/embed/Kx6tjdLqDTQ?si=k2N9wL2QVbrHjjc5" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

#### Immersalについての注意点
現状ではAPIキーを一つだけ使用し、個人的な開発用としてのみ運用しています(Freeプラン)。
ただ、商用利用を想定する場合はプラン管理やAPIキーの管理方法を慎重に検討する必要があります。
https://immersal.com/pricing

また、全ユーザーで共通のマップを利用したい場合には、Niantic ARDKやGeospatial APIの方が適しています。しかし、これらのサービスがARグラスに対応する時期が不透明なため、現時点では今後のプロトタイプ開発を踏まえて、Immersalを利用させて頂いております。

## 開発環境・技術スタック
- Unity 6000.0.32f1 (iOS向け)
- Mac Studio 2022
- iPhone 13 Pro

主な使用ライブラリは以下の通りです。

- Immersal SDK (VPSによる正確な位置合わせ)  
- Firebase Unity SDK (データ管理、認証、AssetBundleの配信)  
- VContainer (依存性注入)  
- UniTask, R3（非同期処理やリアクティブプログラミング）

## 技術的な工夫

### クリーンアーキテクチャの思想を採用
今回の開発では、View層・ドメインロジック層・インフラ層を明確に分離し、疎結合に保つクリーンアーキテクチャとなるように心がけました。

例えば、AssetBundleのリストの取得やダウンロードの際は以下のようにしました。

View層 (PlayerPresenter)  
　→ ドメインロジック層 (AssetBundleUseCase)  
　　　→ インフラ層 (Firebase Storage / Firestore用のクラス)

この設計により、保守性・拡張性を向上させています。
仮にチーム開発を行うことになっても、分担しやすいようにしています。
将来的にスマホからARグラスに移行する際にも、View層の変更だけで済みます。

### 依存性注入による柔軟な設計
依存性注入には軽量でシンプルなVContainerを採用しました。
依存関係を明確化し、メンテナンス性を向上させています。
```csharp:PlayMusicLifetimeScope.cs
    public class PlayMusicLifetimeScope : LifetimeScope
    {
        protected override void Configure(IContainerBuilder builder)
        {
            // リポジトリ・ダウンローダー・サービスの登録
            builder.Register<IAssetBundleRepository, FirebaseAssetBundleRepository>(Lifetime.Scoped);
            builder.Register<IAssetBundleDownloader, FirebaseAssetBundleDownloader>(Lifetime.Scoped);
            builder.Register<IImmersalService, ImmersalService>(Lifetime.Scoped);

            // UseCaseの登録
            builder.Register<AssetBundleUseCase>(Lifetime.Scoped);
            builder.Register<LocalizeUseCase>(Lifetime.Scoped);
            builder.Register<IARSpaceAdapter, ARSpaceAdapter>(Lifetime.Scoped);
            builder.Register<ManageARSpaceUseCase>(Lifetime.Scoped);

            // Presenter の登録
            builder.Register<PlayPresenter>(Lifetime.Scoped);
        }
    }
```

### マップとコンテンツの位置合わせ（ローカライズ）の工夫
オーサリングツール（Editor拡張）でImmersalのサーバーからマップのGLBを取得し、その上にARコンテンツを配置できるようにしています。この時、Editor内でのコンテンツとMapの位置関係が、アプリで見る現実空間でも維持されるように工夫しています。

まずEditor内でマップのGLBモデルの底面中心を原点（0,0,0）に一致させた後、この原点を基準にコンテンツの位置・回転・スケールを設定し、Firestoreへ保存しています。

![スクリーンショット 2025-04-17 14.58.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182279/e3a8caf8-e551-49c2-94e9-9f1cb83dd8c8.png)

アプリ側では、Immersal SDKを用いて実際の空間で位置合わせ（ローカライズ）を行った後、保存しておいた情報をもとに同じMapの底面中心を基準としてコンテンツを配置しています。これにより、Editorで配置した通りの正確な位置関係を現実空間に再現できました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182279/2c29274a-2121-494d-9631-c85144e3c2df.png" width="250"/>

なお、Immersalには本来ARSpaceオブジェクトを用いた標準的な位置合わせの仕組みがありますが、自分の実装の問題か位置合わせが上手くできなかったため、今回のような独自の処理を導入しています。

### 表現力を高めるVFX Graphの活用
UnityのVFX GraphはGPUベースの高い表現力を持つパーティクルエフェクトツールであり、音楽体験を視覚的に豊かにするためにより良いものだと考えています。以下の高橋啓治郎さんのような表現をもっと出来るようになりたいです。

<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="en" dir="ltr">Audio reactive particle effects <a href="https://t.co/swflcCmVbg">https://t.co/swflcCmVbg</a> <a href="https://t.co/vtuF1dGLnz">pic.twitter.com/vtuF1dGLnz</a></p>&mdash; Keijiro Takahashi (@_kzr) <a href="https://twitter.com/_kzr/status/1906345168774783232?ref_src=twsrc%5Etfw">March 30, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ただ、現時点ではAndroidでのAssetBundle利用時に表示出来ないエラーがあったため、開発対象をiOSに限定しています。この問題はUnityのIssue Trackerにも報告する予定です。

## 今後の展望
現在のプロトタイプをベースに、将来的にはARグラスが普及した社会を見据えて改善を続けます。

まずはAndroid向けのアセットバンドルを使用してもVFX Graphが動作するようになった段階で、慣れているSnapdragon Spaces SDK等を使ったグラス向け試作を進める予定です。また、グラス対応していて、かつユーザー間でマップを共有できるVPSインフラが登場次第、それを利用した商用サービスへの移行も検討します。

この個人開発はARグラスの普及期に向けて、5〜10年スパンで継続的に開発を続けていきます。

並行して、携帯電話に類するコミュニケーションを軸としたARアプリにも挑戦したいと考えています。具体的には、リアルタイム通信を使ったインタラクティブなコミュニケーションやAIエージェント同士を用いた情報共有など、他が開発しない新しいコミュニケーションのあり方を模索していく予定です。