見出し画像

VRChat向けアイトラッキング実装テクニック

かれこれ1年半くらい VRChat でアイトラッキングを常用しています。 アイトラッキング用ギミックはほぼ自作しており広く使われている汎用的なギミックとの差異もでてきたため、覚書もかねていったん知見を放流してみます。

VRSNS でのアイトラッキングはなかなかいい感じのハードウェアが出てこなくていまひとつ流行っていない感じはありますが、すでに使っている方や今後導入する方の参考になれば幸いです。


想定読者層

この記事で言及する範囲すべてをカバーしようとするのであれば以下の項目についてある程度理解しているとよいでしょう。

  • VRChat Avatars 3.0 および Unity Animator

  • OSC でパラメータを VRChat に送信するプログラムの記述方法

  • 利用したいハードウェアからアイトラッキング情報を取得する方法

全部拾おうとするとそこそこ大変、かつ筆者の好みの表現によせるためだけの機能も多いため、実際には活用できそうな点だけをつまみ食いしていくとよいと思います。

利用可能なデータ

私が利用している環境 (Droolon Pi1 + 自作ソフトウェア) では以下のデータがアイトラッキングモジュールからの入力として利用できます。 このあたりは利用するハードウェア・ソフトウェアによって差異が大きいため各自の環境に合わせて読み替えてください。

視線

視線の方向が Yaw, Pitch の2軸で得られます。左右の眼の視線が独立して得られる方が注視点の遠近も表現できて好ましいのですが、自作ソフトウェアの機能不足でこのような状態になっています。 他のハードウェア・ソフトウェアだと左右の眼の視線が独立に得られることが多いので視線に関するギミックは左右独立して制御できるように読み替えてやるとよいでしょう。

まぶた

眼ごとに閉じているか開いているかの二値データが得られます。 ハードウェア・ソフトウェアによってはどの程度開いているかを連続値を取得できることがあります。

Native vs. Custom

VRChat 2023.2.1 で、特定のパラメータを OSC で設定することで Avatar Descriptor の情報をもとに視線とまぶたを制御する機能が標準実装されました。 従来の疑似アイトラッキングの設定が済んでいればアバターに特殊なギミックを仕込まなくても使える点は便利なのですが、以下のようにまだ足りてない機能もあるため本稿の実装ではまだアバターギミックとして実装しています。

  • まぶたの状態を左右独立して制御することがまだできない

    • 片目だけ閉じるような動きは別途実装する必要があります

  • アイトラッキングの状態を Animator Controller から利用できない

    • 後述するまばたきとの干渉対策や視線と表情の連動などの実装が難しくなります

視線

視線の表現は Humanoid リグの Left Eye, Right Eye の向きを Additive レイヤーで制御することで行います。 Yaw, Pitch 方向の回転量を [-1.0, 1.0] の範囲に正規化してアバターパラメータとして OSC で送信するため、それを受けて各目の向きを制御する Animator Controller を記述します。

平滑化

OSC で制御されるアバターパラメータの同期頻度は 1-10 Hz 程度とかなり頻度が低いため、同期された値をそのまま視線に使用するとかくついた動きになってしまいます。 この問題への対策として OSCmooth を用いてパラメータを平滑化しています。視線変化への応答が遅くなるデメリットはありますが、もともと通信のレイテンシもそんなに短くないことを考えると妥協できるレベルかと思います。

まぶた

閉じ具合の二値化

目の閉じ具合を連続値として扱うかどうかは好みが別れる点かと思います。 連続値として扱うことで半目のような表現が可能になる一方で、使用者の体調や推定精度などの問題から意図せず半目になってしまったりしやすくなる課題もあります。 今回は意図せず半目になるのを避けたかったため、「閉じている」「開いている」の2状態のみとして扱うこととしました。

まばたき

人間のまばたきは一回あたりおよそ数十ms程度なので、愚直に目の閉じ具合をパラメータにセットするだけだと図 (a) のようにパラメータの同期頻度が足りず頻繁に取りこぼしが発生したり目を閉じている時間が不自然に長くなったりします。 この問題への対策として、リモート側におけるまばたきについては図 (b) のように何回まばたきしたかを別パラメータとして送ってそれに対応する回数だけまばたきアニメーションを再生する形としました。

パラメータ同期タイミングを考慮したまばたきアニメーション

この方針で実装すると以下の動画のようになります。前半が図 (a) のように愚直にローカルと同じ方法を使用した場合、後半が図 (b) のように提案手法を用いた場合となります。 リモート側(右側)の動きを見るとまばたきの同期に起因する不自然な目の動きがかなり軽減されていることがわかるかと思います。

パラメータ構成

上述したまばたきの表現のために、OSC 送信プログラム側で以下のパラメータを計算して VRChat 側に送ります。

  • LClose, RClose

    • ローカル側で使用するまぶたの状態です。

    • 目ごとに閉じているかどうかをそのまま真偽値で表現します。

  • LCloseRemote, RCloseRemote

    • リモート側で使用するまぶたの状態です。

    • まばたき以外の要因で目が閉じているかどうかを各目について真偽値で表現します。

    • 実際には0.1秒以上連続して目が閉じられているときに閉じていると判定されます。

  • Blink0, Blink1

    • リモート側でのまばたきの表現に用いられるカウンタです。

    • まばたきの回数を累計したものを4で割ったあまりを 2bit (2つの真偽値) で表現します。

表情アニメーションとの併用

アイトラッキングだけでもある程度の表現力は得られるのですが、ハンドサインなどによる従来の表情制御と併用することでさらに豊かな表現力を得ることができます。

表情アニメーションとまぶた制御の混ぜ合わせ

よくあるハンドサインによる表情アニメーションを再生するレイヤーの後にまぶたを制御するレイヤーを挿入し、まぶた制御レイヤー側では目を閉じるシェイプを制御することで混ぜ合わせを可能にします。

Animator Controller は Write Defaults Off のステートで構成し、目が開いているときは空のアニメーションを再生することで表情アニメーションによる変化がそのまま、目が閉じているときは目を閉じるシェイプを有効化したアニメーションを再生することで表情アニメーション+閉じ目が出力されるようになります。

まばたき可否フラグ

疑似アイトラッキングのときでもそうであったように一部の表情(笑顔など)シェイプとまばたきに使用するシェイプを同時に用いるとメッシュが破綻してしまうことがあります。 これを回避するため、表情に対応するステートごとにアイトラッキングによるまぶたの制御を有効化するかどうかのフラグを持たせます。

たとえば、左目だけ閉じるアニメーションを再生するためにアイトラッキングによるまぶたの制御を無効化したい場合は図のように Avatar Parameter Driver を用いて左目用の制御可能フラグを折ってやります。 ここでセットされたフラグが立っている場合だけシェイプを操作するようにまぶた制御レイヤーを構築することでまばたきとの干渉を回避することができます。

まばたき可否フラグのセット

干渉するシェイプの打消し

いわゆるジト目などのようにまぶたの制御に用いるシェイプと干渉するがアイトラッキングによるまぶたの制御も行いたいような表情も存在します。 こちらについてはアイトラッキングで使用する閉じ目アニメーション側で目を閉じ切った時に干渉するシェイプの重みが0になるようにプロパティを追加してやることで、目を閉じているときだけ干渉するシェイプの変化を打ち消してやります。

干渉するシェイプを打ち消す閉じ目アニメーションの例

視線との連動

アイトラッキングを利用していると視線の向きを Animator で利用できるようになります。 上下 (Pitch) 方向の視線を利用して下のほうを向いているときにややまぶたを落とすようにしてやると見下ろす時の目の動きがさらに自然になります。 視線に連動する成分と通常の表情アニメーションの混ぜ合わせは Direct Blend Tree を使って図のように記述すると表情を管理しやすくなります。

表情アニメーションと視線連動成分の混ぜ合わせ

おわりに

VRChat アバター向けアイトラッキング実装の細かい改善ポイントをいくつか紹介しました。 ローカルとリモートでの挙動の違いなど複雑なポイントも明示的にケアする必要があったりとまだ発展途上感はありますが、現状でも丁寧に作りこめばアバター越しでの表現力の向上にしっかりと貢献してくれます。

なかなかちょうどよいハードウェアが登場しないために実践以前のハードルが高い状態ではあるのですが、もしアイトラッキング対応ハードウェアを導入する機会があればぜひ試してみてください。 本稿が導入後の細かい調整の一助になれば幸いです。

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