「ARフェス!」開発裏話〜サーバーエンジニア編〜/サーバーの背景にある幾つかの工夫についてご紹介
はじめに
こんにちは!G2 Studios xRディビジョンの泉です。
xRディビジョンで研究開発を行った「ARフェス!」のサーバーエンジニアを担当しておりました。
「ARフェス!」では、MRでのShared ARをテーマとしており、通常の座標を共有しているだけのARと違い、各クライアントに属する情報も全体で共有されています。
このテーマを実現するため、リアルタイムで多数の同期処理を高速・安定して行うパッケージを作成し、「ARフェス!」はそれを使う形で構成しています。
今回は、他ではあまりやっていないであろうこと、他に転用できる内容を3点、ご紹介します。
1:マルチポート処理
1‐1:マルチポート
リアルタイムでのモーションデータ送信のため、基本的にバイナリストリーム通信を行っていますが、双方向通信であるため単純なキュー処理では複数の端末のいずれかの遅延、切断が全体の動作に影響を与える可能性があります。またデータの切断、再接続シーケンスの調整接続管理が煩雑になります。
このため、端末は接続ごとに異なる論理ポートを使用し、切断時でも後述のデータ構造と合わせて新規接続として扱うことで、自動回復をスムーズにおこなえるように実装しました。
1-2:データ基本構造
通信系の開発を行なったことのある方であればご存知かと思われますが、システム的には切断の検出と再開はなかなかうまくいきません。(通信途絶でエラーにならずに、ずっと返ってこないだけになりがち…)
通信環境により頻繁に切断される場合に、スムーズな切断・再接続と、その場合の状態の連続性が必要になります。
※「ARフェス!」の開発環境は、時間帯によって秒単位で切断される状態でした。
このため、通信されるデータ構造は基本的に「最終状態を表すもの」としています。
システムの各状態、演出などの遷移、オブジェクト類の状態変更などは全て数値定義し、クライアントからサーバーはクライアント自身の最終状態、サーバからクライアントはサーバーと全クライアントの最終状態セットが1通信単位になります。
各状態が最終状態として伝達されるので、遅れて接続、再接続によるデータの欠損があっても、現状から線形補完や、単純に開始位置をシフトする等で全体の同期をおこなえるようになっています。
2:データの最小化処理
先のデータ構造をみていると、データが肥大化する可能性が懸念されるかと思います。この問題を回避するために、必要なデータ範囲、構造を確定し、それにより通信データサイズを最小にする措置を幾つかおこなっています。
2-1:空間座標の縮小
メートル単位の位置データの場合、一般的に1データがfloat形式で約±10-38~±1038の範囲で、
1頂点あたりのデータ量は、4bytex3(x,y,z)=12byte、
回転を4元数で行う場合、4bytex3(x,y,z)=16byte、
メッシュの頂点の場合はこれをメッシュ頂点分必要とします。
仮に、固定のメッシュ1が合計で100,000頂点あるとすると、
このオブジェクト1つで、ピボット位置+回転+100,000頂点=1,200,028byte。
例として最初スケールがミリ単位、上限スケールが-10m〜10cm程度必要な場合を想定します。
小数点以下は2桁まで必要で、座標系が-1.0位置を0に変換すれば、データは2.00(-1シフトで1+1)*100>200以下整数となり、
1頂点あたりのデータ量は1x3(x,y,z)=3byte
回転を4元数で行う場合、1x4(x,y,z)=4byte
上のオブジェクト例では、300,007byteで、
およそ1/4のデータ量で済みます。
現在のパッケージでは空間系は基本2byteを基準にしていますが、同じ構成で空間、カラーなどのデータの縮小を行なっています。
2‐2:モーションデータの縮小
キャラクターの動作やクライアントのハンド認識をリアルタイム同期するため、関節動作の同期を行なっています。
上記、2-1のデータ縮小は当然として、媒介変数処理を使用しています。
数学をある程度知っている方であれば、大学で曲率などを習った際に覚えがあるかと思います。関数で複数変数を1パラメータ変数にするものです。
x=f(t),y=g(t),,,変数をtだけにする。
結果的にはUnityにMuscleシステムなるものがあり、これが目的該当のものだったので、素直に使用しています。
これを関節ごとのローカル位置座標・回転各などで行う場合、1関節あたり通常では位置回転で28byte、指を含めると100以上の関節を同期するため3byte以上のデータが必要になりますが、1関節あたりのデータは前述2-1を用いて1byteで処理できるため、単純処理の場合の1/28になります。
3:キャラクター・ハンド処理の双方向リアルタイム処理
「ARフェス!」上では、目に見える部分がないため、通常のARアプリのように各端末でアニメーションを再生しているように見えますが、内部では前述の2-1、2-2による関節情報送信を通じて、キャラクターのモーションデータのリアルタイムでのモーション操作がおこなわれています。
モーションキャプチャなどをサーバーに接続することで、リアルタイムにキャラクターモーションを共有することができます。
また、クライアントにアバターやハンド認識を設定すれば、各端末のハンド認識情報を反映し、他クライアントに自分の動作を認識させることも可能です。
4:同期パッケージの応用例
4-1:動的なポイントクラウドデータのリアルタイム送信
前述2-1のデータの最小化により、数十万頂点の深度/カラーデータをリアルタイムで送信しています。
4-2:リモート共演
複数のモーションキャプチャデータをリモート連動させると同時に、共有空間の所有権の切り替えを行うことで、仮想空間での物品のやり取りなどを可能にします。
※所有権は今後、追加開発予定です。
まとめ
現時点では、同期パッケージとして中立なものを先に作成し、「ARフェス!」を載せる形にしておりますが、パッケージ内継承関係や各インターフェースなども、まだまだ改修の必要があるかなと感じています。
今後もサービスの発展に向けて、改善に取り組んでいきます。
▼G2 Studiosについてはこちら