Home

Awesome

VRMSpringBone-Optimize

大量のVRMモデルを動かすことを想定して、dwango/UniVRMに含まれるVRMSpringBoneC# JobSystem or ECS(EntityComponentSystem) ベースで最適化してみたもの。

Releasesページにて以下の3点を公開している。
それぞれの詳細及び使い方については後述。

※最新環境への対応について(2019/06/20 追記)

現在masterブランチで公開しているものについては既存の公開資料とのバージョンなどを合わせるために、敢えてUnityバージョンや各種パッケージはそのままにしておく想定です。
実用性などを踏まえて保守できる範囲で最新版に追従させているものについてはlasterブランチにて管理していきます。


各種バージョン

依存パッケージ

各モジュールはPackageManagerから取得できる幾つかのパッケージに依存しているので、利用する際には事前に入れておくこと。

表記しているバージョンについては実装時のものとなるが、com.unity.entities以外については恐らくは最新の物が出たタイミングで更新してしまっても問題ないかと思われる。


各モジュールについて

VRMSpringBoneOptimize-Jobs

C# JobSystemベースで実装してみたもの。
ソースについては"VRMSpringBoneOptimize/Jobs"以下を参照。

機能としてはJobのScheduleに関する管理方法の違いで以下の2点を実装している。

導入方法

こちらを有効にするには「ENABLE_JOB_SPRING_BONE」と言うシンボルを定義する必要がある。
→ Assembly Definition側で設定している

使い方についてはCentralizedBufferDistributedBuffer共に設定について大きな違いは無いので、前者を取り上げる形で説明していく。

1. モデルに対する設定

job_model_settings1

2. スケジューラーの生成

job_model_settings2

3. Jobの登録/解除について

VRMSpringBoneOptimize-Entities

C# JobSystem & HybridECSベースで実装してみたもの。
ソースについては"VRMSpringBoneOptimize/Entities"以下を参照。

導入方法

有効にするには「ENABLE_ECS_SPRING_BONE」と言うシンボルを定義する必要がある。
→ Assembly Definition側で設定している

※前述のVRMSpringBoneOptimize-Jobsと似通っている部分が多いのでスクリーンショットは割愛。

1. モデルに対する設定

2. ECS管理クラスの設定

3. Entityの登録/解除について


パフォーマンスについて

以下の環境でニコニ立体ちゃんのVRMモデル256体を同時に動かすデモを実装して負荷計測を行ってみたので、参考までに結果について記載していく。

performance_demo

オリジナル

先ず最初に既存の処理の結果から載せていく。
MainThreadベースで処理されているLateBehaviourUpdateの負荷が支配的な印象。
動的なモデルの増減に関してはそこまで負荷が掛かっていない様に見受けられる。
※Memoryの項目でスパイクが発生している箇所辺りでモデルの追加を行っている。

original

VRMSpringBoneOptimize-Jobs(CentralizedBuffer)

こちらは一括で処理を行うタイプのJobSystemベース実装。
IJobParallelForTransformで物理演算及びTransformの反映を効率よく行えているためか、パフォーマンスとしては4つ挙げた例の中でも一番良い結果となった。
問題点としては上述のデメリットの項目にもある通り、動的なモデルの追加/削除を行った際にバッファの再構築が入るので負荷が高い。(2つほどある巨大なスパイクがそれ)

job_centralized

VRMSpringBoneOptimize-Jobs(DistributedBuffer)

こちらはモデル毎に処理を行うタイプのJobSystemベース実装。
Scheduleの回数が多いためか処理の纏まりが悪く、定期的にスパイクも発生している印象。
モデルの増減については目立った負荷は見受けられず。
※こちらもMemoryの項目でスパイクが発生している箇所辺りでモデルの追加を行っているが、追加/削除による負荷は無い様に見受けられる。(定期的に見受けられる青色のスパイクは別の要因で発生しているもの)

job_distributed

VRMSpringBoneOptimize-Entities

最後にECSベースの実行結果。
VRMSpringBoneOptimize-Jobs(CentralizedBuffer)に近いぐらいのパフォーマンスは出ている感。
モデル追加/削除の負荷についてはCentralizedBufferほどで無いにせよTransform周りのバッファ構築の影響で負荷が掛かっている様に見受けられる。

ECSと言えどもHybrid且つメモリ周りについてもそこまで効率化している実装ではないので、結果としてはCentralizedBufferと比べるとデータの管理方法が変わっただけという感じとなった。
※ちなみに、モデル追加/削除時の負荷についてはTransformを持つアーキタイプの数が増えれば増えるほど更新されるTransformAccessArrayの数が多くなり、その分負荷が上昇してくるので注意する必要がある。

ecs


License