Unity を検索

オンデマンドレンダリングでモバイルのパフォーマンスが向上するしくみ

2020年2月7日 カテゴリ: テクノロジー | 4 分 で読めます
取り上げているトピック
シェア

理由はさまざまですが、特にモバイルプラットフォームでは、プロジェクトを可能な限り高いフレームレートでレンダリングすることが必ずしも望ましいとは限りません。これまで Unity 開発者は、Unity のレンダリングスピードを抑えるために Application.targetFrameRate や Vsync Count を利用してきました。このアプローチは、レンダリングだけでなく Unity のさまざまな要素が実行される頻度にも影響します。新しいオンデマンドレンダリング API を使用すれば、レンダリングの頻度をプレイヤーループの頻度から切り離すことができます。

オンデマンドレンダリングとは

オンデマンドレンダリングでは、フレームのレンダリングをスキップしながらも、引き続きプレイヤーループの残りの部分を高い頻度で実行することができます。これは特にモバイルで強みを発揮します。レンダリングを回避することで、タッチイベントに対するアプリケーションの応答性を維持しつつ、パフォーマンスと省電力性を大幅に向上できます。

オンデマンドレンダリングを使う理由

フレームレートを下げる余地がある例をいくつか紹介します。

  1. メニュー(アプリケーションのエントリポイントや一時停止メニューなど):メニューは比較的シンプルなシーンになる傾向があり、そのような場合にはフルスピードでレンダリングする必要はありません。低めのフレームレートでメニューをレンダリングしたとしても、レンダリングされていないフレームの間に入力を受け付けることができるので、電力消費を低減して、CPU 周波数が抑制されるレベルまでデバイスの温度が上昇しないようにしつつ、滑らかな UI 操作を維持できます。
  2. ターンベースのゲーム(チェスなど):ターンベースのベームでは、ユーザーが次の動きを考えている間や他のユーザーの動きを待っている間に、アクティビティが減る時間が発生します。そのような時間にはフレームレートを下げることによって、不必要な電力の使用を防ぎ、バッテリー寿命を延ばすことができます。
  3. 静的コンテンツ:自動車のユーザーインターフェース(UI)など、大半の時間コンテンツが静的なアプリケーションでは、フレームレートを下げることができます。
  4. パフォーマンス管理:バッテリーをできるだけ長持ちさせたり、CPU スロットリングを回避したりするために電力使用量とデバイス温度を管理する場合(特に Adaptive Performance パッケージを利用している場合)は、レンダリングスピードを調整できます。
  5. 機械学習アプリケーションや AI アプリケーション:CPU がレンダリングに費やす作業量を減らすことで、アプリケーション本来の目的である高負荷処理のパフォーマンスが若干向上する可能性があります。

サポート対象

オンデマンドレンダリングは、サポートされているすべてのプラットフォーム(システム要件を参照)とレンダリング API(組み込みのレンダーパイプライン、ユニバーサルレンダーパイプライン、HD レンダーパイプライン)を備えた Unity 2019.3 で機能します。

オンデマンドレンダリングの使い方

オンデマンドレンダリング API は、名前空間 UnityEngine.Rendering のたった 3 つのプロパティーで構成されます。

OnDemandRendering.renderFrameInterval
これがもっとも重要なプロパティーです。これにより、レンダーフレーム間隔を取得または設定できます。これは、新しいフレームレートを定義するための Application.targetFrameRate または QualitySettings.vSyncCount の分割係数です。たとえば、Application.targetFrameRate を 60、OnDemandRendering.renderFrameInterval を 2 に設定すると、1 つおきのフレームだけがレンダリングされ、フレームレートは 30fps になります。

OnDemandRendering.effectiveFrameRate
このプロパティーを使うと、アプリケーションがレンダリングする際のフレームレートの概算値を得られます。この概算値は、OnDemandRendering.renderFrameInterval、Application.targetFrameRate、QualitySettings.vSyncCount の値とディスプレイのリフレッシュレートを使用して決定されます。ただし、あくまでも概算値であって、保証された値ではないことを忘れないでください。CPU がスクリプト、物理演算、ネットワークなどの他の処理に使用されてしまうと、アプリケーションのレンダリングスピードが低下する可能性があります。

OnDemandRendering.willThisFrameRender
このプロパティーでは、現在のフレームを画面にレンダリングされるかどうかを指定するだけです。レンダリングされないフレームは、高負荷の演算処理、アセットのロード、プレハブのスポーンなど、CPU 負荷の高いその他の処理に使用できます。

その他の知っておくべきポイント

  • フレームがすべてレンダリングされるわけではないとしても、イベントは通常のペースでスクリプトに送信されます。つまり、レンダリングされないフレームの間も入力を受け取る可能性があります。入力ラグの発生を避けるには、入力中は OnDemandRendering.renderFrameInterval = 1 を呼び出して、ボタンや操作などの応答性を保持することをお勧めします。
  • スクリプティング、物理演算、アニメーションなどに非常に高い負荷がかかっているにもかかわらず、レンダリングが行われていない状況では、オンデマンドレンダリングを使用するメリットがありません。その状況でオンデマンドレンダリングを使用しても、効果にはムラがあり、CPU や電力の使用量の低減はほとんど低減されない可能性があります。

オンデマンドレンダリングをメニューで使用して、入力がない間は 20fps でレンダリングされるようにする簡単な例を次に示します。

using UnityEngine;
using UnityEngine.Rendering;

public class Menu : MonoBehaviour
{
    // 最初のフレームが更新される前に Start を呼び出します
    void Start()
    {
        QualitySettings.vSyncCount = 0;
        Application.targetFrameRate = 60;
	   // メニューが起動したら、レンダリングのターゲットを 20fps に設定します
        OnDemandRendering.renderFrameInterval = 3;
    }

    // 1 フレームに 1 回 Update が呼び出される
    void Update()
    {
        if (Input.GetMouseButton(0) || (Input.touchCount > 0))
        {
            // マウスクリックやタッチ操作が検出されたら、(フレームごとに)60fps でレンダリングします
            OnDemandRendering.renderFrameInterval = 1;
        }
        else
        {
            // マウスやタッチによる入力がない場合は(3 フレームごとに)20fps に戻します
            OnDemandRendering.renderFrameInterval = 3;
        }
    }
}

オンデマンドレンダリングをさまざまなシチュエーションで活用できることを紹介したサンプルプロジェクトは、こちらから入手できます。

オンデマンドレンダリングをご利用の皆さまへ

オンデマンドレンダリングを使用したご感想を、ぜひフォーラムでお聞かせください。Windows、macOS、WebGL、iOS、Android については、Unity Editor とスタンドアロンプレイヤーの両方でテスト済みですが、皆さまからのフィードバックをいつでもお待ちしております。

2020年2月7日 カテゴリ: テクノロジー | 4 分 で読めます
取り上げているトピック