[VRChat] DynamicBoneがパフォーマンスに与える影響の調査報告

DynamicBoneに関して、処理が重い、いやそんなに重くない、Gravityが重い、いや実は重くない等々、色々な情報が錯綜しており自分自身気になったので調査してみました。

注意としては僕自身は普段はHTMLを書いている人間で、Unityやゲーム制作は完全に素人です。出来るだけ意味のある検証をしようとはしましたが本職の人から見たら見当違いな事をしている可能性もあるので、もし変なとこあればバシバシ突っ込んでもらえればと思います。

8/4追記

DistantDisableはVRChat内で自動的に有効化される事を確認しました。(強制的にDistantDisableにチェックが入り、Distance to Objectに10の値が入った状態になる。Distance to Objectに5等の小さい値を設定した場合でも10の値に強制的になります)

なので、2018/08/04現在ではユーザーがDistantDisableとDistant to Objectの設定を弄っても意味がありません。

結論

詳細が結構長いのでまず結論を。

  • Gravityを設定しても負荷は変わらない
  • UpdateRateを下げてもほとんど軽くならない
  • DistantDisableは軽くする効果が大きいので設定してほしい(その際は、DistanceToObjectを出来るだけ小さい値にしてほしい)

検証方法

  • UnityのProfilerで検証
  • シーンに20体のみここモデルを配置し、DynamicBoneを設定(みここはCandyRockStarを踊らせている)
  • 検証端末のCPUは i5 8400

Unity上で検証した理由は、レンダリングの問題ではないのでVR環境である必要性は無いと判断したためです。念の為、一部VRChat上で結果が同じか確認したのですが、Unity上での検証と結果は変わりませんでした。

検証パターンは以下の通りです。

  • DynamicBoneなし
  • DynamicBoneあり
  • DynamicBoneあり(Gravityに値を入力)
  • DynamicBoneあり(上に加え、DynamicBoneColliderを配置)
  • DynamicBoneあり(上に加え、UpdateRateを30に)
  • DynamicBoneあり(上に加え、DistantDisableを有効に)

DynamicBoneなし

no_dynamic_bone

上の2.1msがRendering(描画)、下の0.9msがOthers(カテゴリ分けが難しいもの)に消費されている時間です。

DynamicBoneの処理に消費される時間は、青色のScripts(スクリプト)で表示されます。今はDynamicBoneを設定していないのでほぼ表示されていませんね。

DynamicBoneあり

dynamic_bone

  • ツインテール

に対してデフォルト設定のDynamicBoneを設定した状態です。DynamicBoneの処理時間は1.5msになっています。

1.5msと見ると短く感じますが、90FPSを目指す場合1フレームの処理時間は11msです。使用できる処理時間の1割以上をDynamicBoneだけで使ってしまっているので決して軽い処理とは言えなそうです。

DynamicBoneあり(Gravityに値を入力)

dynamic_bone_with_gravity

DynamicBone全てのGravity:Yに「-0.02」を設定した状態の物です。処理時間は変わらず1.5msなのでGravityは特に重い処理ではないようです。

実際DynamicBoneのソースを確認したのですが、Gravityの有無で処理が重くなるような箇所も見当たらなかったのでこの結果は妥当かと思います。

DynamicBoneあり(上に加え、DynamicBoneColliderを配置)

dynamic_bone_with_gravity_and_collider

体に2箇所、袖に影響するColliderを設定した物です。処理時間は0.3ms増えて1.8msです。

たった2箇所のColliderで処理時間がこれだけ増えたので、Colliderだらけのアバターはかなりやばいことになるかと…

DynamicBoneあり(上に加え、UpdateRateを30に)

dynamic_bone_with_gravity_and_collider_rate_30

ここからはDynamicBoneの処理を軽くするための設定の検証です。

UpdateRateは1秒間に何回DynamicBoneを更新するかの設定です。デフォルトが60なので半分の設定にしてみました。

結果は1.7msと0.1msしか短くなっていません。流石に不思議に思って調べた所、UpdateRateが小さい場合に処理をスキップするための処理「SkipUpdateParticles」があるのですが、それが結構重い処理になっていました。

ColliderだらけのDynamicBoneならそれなりに有用な設定では有ると思いますが、そうでなければUpdateRateは処理負荷に関してはあまり影響しないので注意してください。

DynamicBoneあり(上に加え、DistantDisableを有効に)

dynamic_bone_with_gravity_and_collider_distance_5

こちらはDistantDisableを有効にした上でDistanceToObjectに5を設定したパターンです。(手前3体のみDynamicBoneが動いています)

こちらは処理負荷が0.6msまで落ちており、UpdateRateと異なり有効に働いています。


DynamicBoneを使用する時はDistantDisableを有効にし、DistanceToObjectを出来るだけ小さくしてもらえると周りに優しいかと思います。

(冒頭の追記の通り、VRChat内では強制的に設定が有効化されます)

以上

パフォーマンスに関しては体感しやすいので結構雰囲気で語りがちなのですが、実際に調査してみると意外な結果になったりしますね。

現在運営しているワールドはパフォーマンスでかなり困っている(20人超えたあたりからCPU負荷がやばい…)ので、こういう負荷調査の記事が増えたら良いなと思って書きました。

宣伝

img_feature_dancehall01

Silent Clubというワールドを作りました。ボイスチャット強制ミュートのワールドです。パブリック化しておらず、基本的に週に1回の開店です。

制作は僕とシリンダさんの二人。ざっくり分担はシリンダさんが見た目部分(Blenderでのモデリング、ライティング等)やギミックのアイデア、僕が技術的な部分(エフェクトやギミックの実装等)やWEBサイトの制作になります。制作着手から先日の正式オープンまで大体2ヶ月程度でした。

(僕含む)会話が苦手な人もそうでない人も一緒に楽しめる場があったらいいなと思って作ったので是非。「VRChat始めたけど会話が…」って人を見かけた際には是非勧めて頂ければと思います。