負荷を抑える
最初に、重さの種類を見分ける
Section titled “最初に、重さの種類を見分ける”このページは、オーバーレイを出すと VR 全体が重くなる、またはオーバーレイの動きだけがカクつくときに、負荷の原因を見つけて減らす手順です。VR の中で動くので、オーバーレイの負荷は、VR 体験全体の快適さに響きます。
最初に、重さの種類を見分けます。同じ VR アプリ・同じ操作で、オーバーレイを起動した状態と終了した状態を比べてください。
| 観点 | 当てはまるとき |
|---|---|
| オーバーレイを終了しても、VR が重い | VRChat や GPU のドライバーなど、FloatSoda の外に原因がある。このページでは直せない |
| オーバーレイを出したときだけ、VR が重い、またはオーバーレイの動きだけがカクつく | FloatSoda のアプリ側で調整できる。手順 1 へ進む |
調整できる箇所は 3 つです。フレームレートの設定、再描画の範囲、更新の頻度です。
手順1: 負荷を測る
Section titled “手順1: 負荷を測る”変える前の値を控えます。値を控えておくと、調整のたびに、効いたかどうかを数字で比べられます。
測る値は、フレームレートと GPU の使用率の2つです。FloatSoda に計測の機能はないので、SteamVR と Windows の表示を使います。SteamVR でフレームの時間を表示する方法は、Valve の SteamVR の資料にあります。
毎回同じ操作(たとえば、ダッシュボードを開いて 30 秒眺める)で測ってください。
できた? 変える前の値が手元にある。
手順2: フレームレートの設定を下げる
Section titled “手順2: フレームレートの設定を下げる”目標のフレームレートは FloatSodaOptions.TargetFrameRate で決まり、既定は 60 です。メインループと描画ループの両方がこの値に合わせて動くので、下げると処理の回数が減ります。
builder.Services.AddFloatSoda(new FloatSodaOptions{ TargetFrameRate = 30,});1 以上の整数を指定します。0 以下にすると、起動時に ArgumentOutOfRangeException になります。値を下げると、アニメーションの描き換え回数も減るので、動きは粗くなります。
値を下げて起動し、手順 1 と同じ操作で測り直します。
できた? 値の変化が数字で見える。
手順3: 再描画の範囲を絞る
Section titled “手順3: 再描画の範囲を絞る”FloatSoda は、変わった部分だけを作り直し、そのレイアウトと描画をやり直します。変更のないフレームでは、レイアウトと描画を行いません。範囲を絞ると、やり直す処理が減ります。絞る方法は 2 つあります。
1 つ目は、RepaintBoundary で囲むことです。RepaintBoundary で囲んだ子は、独立した描画の層に分けられます。囲んだ中だけが変わっても、外側は描き直されません。省けるのは描画だけで、ウィジェットの作り直しとレイアウトは省けません。
new Column{ Children = { new Text("見出し(変わらない)"), new RepaintBoundary { Child = new CounterWidget(), // 頻繁に変わる部分 }, },}2 つ目は、SetState() を呼ぶ State を小さく分けることです。SetState() は、その State を持つウィジェットの下を作り直します。頻繁に変わる値は、その値を表示する小さなウィジェットの State に持たせると、作り直す範囲が狭くなります。画面全体のルートで SetState() を呼ぶと、画面全体が作り直されます。仕組みは 状態と作り直し にあります。
頻繁に変わる部分を囲み、測り直します。
できた? 測り直した値が下がり、見た目と操作感が変わっていない。
手順4: 更新の頻度を減らす
Section titled “手順4: 更新の頻度を減らす”更新の頻度を減らす方法は 3 つあります。該当するものを直します。
- タイマーで
SetState()を呼んでいる場合は、必要な表示頻度に合わせて、更新の間隔を長くすることが望ましい - 不透明度を動かすために
SetState()を毎フレーム呼んでいる場合は、FadeTransitionに替えること - 固定の
SizedBoxなどで足りる場合は、IntrinsicWidthとIntrinsicHeightを避けることが望ましい
理由は次のとおりです。画面に見える変化が必要な頻度より短い間隔で更新していると、見えない更新に処理を使います。FadeTransition は、アニメーションの値を再描画だけで反映するので、1 フレームごとの SetState() が要りません。IntrinsicWidth と IntrinsicHeight は子の自然な大きさを調べるためにコストが高く、多用すると負荷が上がります。
あわせて、次の 2 点も負荷に関わります。
- 画面のピクセル数が大きいほど、描画する面積が増えます。ピクセル数は
Sizeで決まり(省略するとレイアウト結果の大きさになります)、VR 内の実寸はDpmで決まります。DashboardWindowではDpmが表示サイズに影響しない場合があります(レイアウトの考え方)。必要以上に大きな画面にしないことが、負荷を抑える手段になります。 - 複数のウィンドウを同時に出すと、ウィンドウごとにレイアウトと描画の処理が行われます。使っていないウィンドウは作らないでください。
できた? 測り直した値が下がる。
結果を確かめる
Section titled “結果を確かめる”手順 1 で控えた値と、調整後の値を、同じ操作で測って比べます。調整は 1 つずつ行い、そのたびに測ります。フレームレートが上がった、または GPU の使用率が下がり、動きと操作感が許容できれば、調整は効いています。効果がない、または操作感が悪化した変更は、元に戻します。
それでも直らないとき
Section titled “それでも直らないとき”直らないときの行き先は、ガイドの docs で見つからないとき にあります。聞くときは、次の情報を添えてください。
- 測った値(調整前と調整後、測った道具)
- ウィンドウの数と種類
- 画面の大きさ(
SizeとDpm) TargetFrameRateの値