背景

弊社ではXR事業の取り組みとして Buralit というプロダクトを開発しています。

こちらは、従来 Unity ベースで構築していましたが、後述する背景や理由があり React Three Fiber (R3F) ベースへの移行(リプレース)を行いました。

その際の気づきなどをフィードバックしたいと思います。

なお、この内容は XR Kaigi 2024 で講演した内容をもとに加筆したものです。

スライドへのリンクは こちら です。

Buralitって何?

Buralitは、360度カメラで撮影した動画や静止画をベースとしたバーチャル空間を、アバターで自由に回遊できる観光メタバースサービスです。

ユーザーはアバターを使ってバーチャル空間内の日本地図上を移動制限なくシームレスに探索し、各地の観光スポットを見て回ったり、空間内でグループを作ってコミュニケーションをとりながら探索することができます。

React Three Fiber (R3F) って何?

React Three Fiber (R3F) は、3Dコンテンツ制作に使われる Three.js を、 Reactのコンポーネントのように扱えるようにするラッパー的な位置づけのライブラリです。

ドキュメント にあるように、3Dコンテンツをコンポーネントのようにして、Reactアプリケーション内に表示できます。

参考までに、UnityとR3Fの機能対照表を挙げておきます。(記事作成時点の情報です)

機能カテゴリ Unity React Three Fiber(R3F)
基本用途 ゲーム開発、VR/AR、シミュレーション、アニメーション、インタラクティブアプリ Webブラウザ向け3Dコンテンツ
エンジンの基盤 独自エンジン(高機能だがやや重い) Three.js(WebGLベースで軽量)
プラットフォーム対応 クロスプラットフォーム(PC, モバイル, コンソール, Web, XRデバイス) Web専用(PCおよびモバイルブラウザ)
開発言語 C# JavaScript/TypeScript
ビジュアルエディタ 高度な統合ビジュアルエディタあり 専用のエディタはなし
リアルタイムレンダリング 高性能なリアルタイムレンダリング Three.jsの性能に依存
物理エンジン 内蔵の高性能物理エンジン(NVIDIA PhysXやHavok) 基本的な物理機能(@react-three/rapierなどの外部ライブラリを利用可)
アニメーション ビジュアルエディタおよびスクリプトで高度なアニメーション制作が可能 基本的なアニメーション(Three.jsまたは外部ライブラリ依存)
拡張性 アセットストアやプラグインで機能拡張可能 npmパッケージやThree.jsエコシステムの活用
コミュニティとサポート 大規模で成熟したコミュニティ、多くのドキュメントとフォーラム Reactエコシステムを活用可能、コミュニティは拡大中
学習コスト 初心者には高め(ツールとスクリプトの習得が必要) React経験者には低い
ライセンスモデル パーソナル版無料、有料プランあり(収益による制限や条件あり) 無料(Three.jsとReactのオープンソースライセンスに基づく)

Webブラウザでの3D表示に特化したR3F、ゲームなどのために多様な機能にも対応しているのがUnity、といえると思います。

なぜ移行しようと思ったか

開発サイクル、リリースサイクルの高速化

Buralitはもともとスマホ向けアプリとしてAndroid/iPhoneに提供していました。しかし、アプリインストールなどが手間であることから、より簡単に楽しめるブラウザ版(WebGL版)を追加でリリースしました。

このとき、WebGL版に一本化してもよかったのですが、すでにアプリ版を利用しているユーザーの便宜や、ネイティブ機能との相性などを考えた結果、一本化はせず3種類のアプリを提供する形となりました(といってもコードベースは共通ですが)。

よって、動作確認時やリリース時には、WebGL/Android/iPhone用にそれぞれビルドして動かす必要があるのですが、

  • iPhone版はMac OSの動くPCでないとビルドできないが、開発メンバー全員分は確保しておらず、手待ち時間が発生
  • リリース時、各ストアの審査を通す必要があり、ビルド時間に加えて審査の日数がかかる

といった課題があり、「ビルドや端末の空きを待つ時間を減らして、サクサク開発したい!」という思いがありました。

 

将来的なスケールの可能性

将来的にXR事業を拡大する可能性を考えたとき、以下の点がネックになりうると判断しました。

ライセンス費用の問題

弊社の場合、 Unity Industryライセンス が必要になります。そのため、メンバーを増やして開発をしようと思うと、ライセンス費用だけでかなりの費用が掛かってしまいます。

技術者の少なさ・技術ハードルの問題

弊社ではUnity技術者の絶対数が少なく、逆にWeb技術者のすそ野は非常に広いのが現状です。XRに興味を持ってもらい、シフトしてもらうとしたら、Web技術であるR3Fのほうが親しみやすいでしょう。それに先立ち、R3Fでの事例を作っておく必要がありました。

 

起動時間(画像・動画読込時間)の増大

Buralitは観光地の画像や360度画像を楽しんでもらうプロダクトですが、既存のアプリの作り上、最初に全画像・全動画をダウンロードする作りになっていました。

最初のうちは問題なかったのですが、掲載箇所が増えて画像や動画が増えるにしたがって、どんどん起動が遅くなり、最終的には5分くらいは待つ状態になってしまっていました(回線によってはもっとかかるか、途中で切れてリトライ…)。

その後も掲載箇所が増える予定があったため、早急に改善施策が必要でした。もちろん、Unityのまま、アーキテクチャなどを見直すことで対応できる可能性もあったかもしれませんが、上記の他の理由もあり、R3F版に乗り換える中で対処することとしました。

どうやって移行したか

前提

Buralitは開発中のプロダクトであり、機能追加は止めずに移行を進める必要がありました。
また、UnityからR3Fに移したとしても、プロダクトとしての価値があがるわけではないので、工数・工期を極力抑える必要もありました。

 

進め方

上記の前提から、機能を洗い出してマッピングしてプロトタイプして…という教科書的なやり方ではなく、とにかくできるところから進めよう、という進め方で進めていきました。具体的には以下のような流れです。

とにかくプロトタイピング

まず既存アプリの基本的な体験(3D空間上に360度画像を映して、その中でアバターが走り回る)ができるサンプルアプリケーションを、R3Fで新規作成しました。

共通機能として落とし込む

上記のサンプルアプリケーションをベースに、共通機能を徐々に追加していきました。

もともとUnityのときは Extreal という自社フレームワークに沿って開発していました。

そこで提供していた機能を徐々にR3Fベースに変えて、 R3Fでの共通機能(参照実装)を作っていきました。

ひたすら機能を移植

カメラやアバター、360度画像表示などの共通機能ができあがってきたら、既存のアプリケーション画面をR3Fで実装していきました。UnityからR3Fに自動変換するツールなどはないので、画面を見比べながら、ほぼ新規作り直しでした。

とはいえ、作るものはすでに明確でしたし、アプリの性質上、物理演算など複雑な処理は特にないため、UIをReactで実装することに慣れてくれば、割とスムーズに移植を進めていけました。

スムーズに進んだ背景として、以下のようなReactならではメリットもありました。

  • Storybook を使っての開発で、UIをコンポーネント単位で確認できたこと
  • ホットリロードが高速でビルド待ち時間が大幅に減ったこと
  • コンポーネント単位で開発を進められるため分担作業が容易だったこと

なお、アニメーション部分については、Unityだと .anim という独自形式で管理されていたため、 .vrm.vrma 形式に変換、または新規作成して対応しました。

いつ頃終わったか

2024年6月頃から着手し、9月末には、追加機能を含めてR3F版への移植はおおむね完了しました。
性能対策にしばらく手間取ってしまいましたが、2024年10月末にR3F版をリリースできました。

想定通りの効果があったか

総じて、想定通りの効果があったと考えています。

 

開発サイクル、リリースサイクルは高速化した

ソースコードの修正が、ブラウザ上ですぐ反映されるため、開発効率・開発者体験は向上したといえます(計数化は難しいですが)。Unityは、実行中どうしてもマシンが重くなることがあったのですが、R3F版では特に気になることもなく、軽快に操作できていると感じています。

また、リリース作業も省力化されました。特に、スマホ向けのビルドや審査待ちがなくなったのが大きいです。

体感ですが、Unity版ではビルド・デプロイに30分~1時間(リリースの場合はストアの審査で+1~3日)程度かかっていたところ、R3Fではビルド・デプロイ・リリースまで15~30分程度(スマホアプリはないため審査期間なし)でできるようになっています。

なお、「Unity版のまま、WebGLに絞れば同じことだったのでは?」と思われるかもしれませんが、Unity版の場合は掲載スポットの画像の追加や差し替えがあると、Unity向けの資源(Addressable Asset)のビルドが必要となっていました。このビルドや転送にも相当の時間がかかっていました。

R3F版に変える際、画像や動画などの資源は特に1つに固めずに、都度CDN経由で取得するようにしたため、アセットのビルド時間も不要となりました。この点でもリリース作業を省力化できました。

 

Web(特にReact)経験者からのシフトは十分可能

3Dの知識が必要な部分はR3F版フレームワークで吸収できていたこともあり、過去にWebアプリやReactの開発経験があるメンバーについてはスムーズにR3Fでの実装に対応できていました。

一方で、Unity経験しかないメンバーがシフトするには難しい面があったと考えています(後述)。

 

Buralitの起動時間が高速化した

R3F版では事前に全画像・動画を読み込むことはせず、必要になったときに読み込む形になったため、アプリの起動は数分ほどかかっていたところから数秒まで高速化しました。

ユーザーへの影響という観点では、この点が最も価値の高い効果だったといえるでしょう。

移行に際して/終わっての困りどころ

移行時、あるいは移行してから判明した課題を以下に整理しておきます。

 

UnityからR3F間の、技術ギャップ対応の属人化

起きたこと

カメラやアバター移動、3Dアニメーションなど、Unityの機能に頼っていた部分については、自分たちでどうにかする必要がありました。今回、その部分は技術的素養のある少数のメンバーで集中的に実装し、フレームワークという形で開発者に提供しました。その結果、フレームワークチーム以外のメンバーについては「R3Fで動くアプリは作れたけど、どうやって動いてるのかはよくわからない」状態になってしまっています。

学び・対策

フレームワーク検討時の資料などをもとに、開発者向けにガイドやWikiとして情報を整理するようにしています。

 

Unity技術者の、R3Fへのスイッチングコスト

起きたこと

今回、体制は大きく変えず、開発メンバーはそのままでR3Fへの移行を進めました。UnityとR3Fでは求められるスキルセットが大きく違うこともあり、Unity技術者がR3Fを学習する期間をかなり多くとることになりました。

学び・対策

R3Fでの実装には、R3Fそのものはもちろん、ReactやCSSなどWeb開発一般についての前提知識が必要になります。今後同じようにR3Fについて学習するメンバーがいた場合のために、当時の学習内容や学習資源をWikiとして整理するようにしています。

 

アーキテクチャ見直しによる再開発

起きたこと

できるところから進めていった結果、構造がよくない部分やコンポーネントの分け方が不十分な部分、動きがわかりにくい部分が散見されるようになってきました。事後的にアーキテクチャを見直して修正していきましたが、その頃にはある程度機能ができあがっていたため、修正とテストでかなり手戻りが発生してしまいました。

R3Fに限らず、どのようなアーキテクチャが最も望ましいかは一概には言えず、ある程度トライアンドエラーが発生するのは避けられないところではあります。ただ、今回の移行においてよくなかったのは、アーキテクチャの検討期間や見直し期間が想定されていなかったことです。このため、開発途中での計画変更、リスケが必要となってしまいました。

学び・対策

当たり前の話かもしれませんが、移行やリプレースのようにプログラム構成が大きく変わる(あるいは新規作り直しになる)場合は、アーキテクチャの見直しタイミングとその反映期間を計画に織り込んでおく必要があります。

 

リリース前の性能問題

起きたこと

以下の画像のように、Buralitでは地図上にスポットのサムネイル画像を表示するようになっています。

性能テスト中、多数のスポットがある地域を表示した際に、iPhoneにおいてブラウザの強制リロードが行われる事象が見つかりました。

調べたところ、

ことがわかりました。

R3F版への移行と並行して、特定地域にスポットが一気に増えたことも影響した事象でした。

学び・対策

メモリ対策として以下のように対応しました。

  • 画像圧縮
    • 360度画像や動画からの切り出しをそのまま使うのではなく、画質や解像度を調整した画像を使う
    • メモリ使用量が少なくて済む KTX2 に変換する
  • 処理の見直し
    • 画面を行き来したときに、@react-three/fiberのCanvasコンポーネントが残り続けるような挙動をしていたため、都度作り直さないように構成を見直し
    • @react-three/drei のOutlineコンポーネントを使っている箇所でメモリが多く使用される傾向があったため、自作コンポーネントに差し替え

補足事項

今回、短期間でR3Fへ移行できたのは、Buralitというプロダクトが、3D表現をフルに活用したゲームというよりは通常のWebアプリケーションに近かったから、という側面もあると思われます。

  • たとえば、Buralitでは物理演算などは使用していませんし、操作はゲームパッドなどではなくマウスやキーボードのみです
  • また、VR対応も行っていません

よりUnityライクな本格的なゲームであったり、よりVRに特化したアプリケーションなどの場合は、事前に技術マッピングやプロトタイピングをしたうえで移行可否の判断をすることをお勧めします。

おわりに

UnityからR3Fへの移行事例をご紹介しました。

両方触ってみたうえでのよいところ・課題になるところを整理すると、以下のようになると思います。

Unity React Three Fiber
よいところ 機能が豊富で、ワンストップで何でもできる。アニメーションも3Dモデルもエディタ上で作成でき、足りないものはアセットストアから追加することもできる。 軽量な動作。ホットリロードにより修正内容がすぐに反映される。

Reactベースなので、Storybookなどのツールの活用により、コンポーネントをわけて効率よく開発を進めることができる。

課題になる

ところ

やや動作が重い。快適に使おうと思うと、ある程度スペックのあるPCが必要になる。

エディタ機能の使い方とC#スクリプトの両方の知識が必要となり、未経験者からのハードルが高い。

3Dモデルやアニメーションなどを別口で用意する必要がある(専用のツールが必要)。

CSSに関する知識がないとUI周りの実装が難しい。そのため、Web開発未経験だとハードルが高い。

3Dアプリケーションを作る上での表現力や付随機能の豊富さなどでは、Unityのほうが優れているでしょう。一方で、ライセンス費用の問題であったり、機能が多いがゆえの学習面のハードルもそれなりにあるといえます(どこに何があるのか、何ができるのか覚えるだけでも結構大変かと…)。

「がっつりゲームというわけではないのだけど、3Dで動くアプリケーションを作りたい」という用途であれば、R3Fも有力な選択肢になるでしょう。Web開発、特にReactの経験があれば、ゼロからUnityを学びなおすよりは入りやすいと思います。R3Fに関する入門者向けの書籍などは多いとはいえませんが、有志によるドキュメントや、 R3F版Extreal の情報なども参考に、チャレンジしてみてはいかがでしょうか。

皆様の参考になれば幸いです。