LoginSignup
32

More than 3 years have passed since last update.

【Unity】オンデマンドレンダリングで描画処理負荷を抑える

Last updated at Posted at 2020-04-03

はじめに

Unity 2019.3からオンデマンドレンダリング(On-demand rendering)なるものが追加されました。1
レンダリングのパフォーマンスには苦労することの多いモバイルアプリ開発などで特に有用そうな機能でしたのでご紹介します。

どういうもの?

ゲームループ(MonoBehaviour.Updateとか)のフレームレートは通常通りに、レンダリングを一定間隔でスキップできる機能です。
normal_rendering.png

ondemand_rendering.png

これの一番の使いどころは(特にモバイル端末での)「レンダリング処理負荷低減」でしょう。
例えばユーザー入力待機画面のような画面の動きが激しくない(=見た目のフレームレートを落としても影響が小さい)場面なら、レンダリングを適度にスキップすることでクオリティそのままに端末の発熱や消費電力を減らすことが期待できます。

また、従来からあるフレームレート調節方法であるApplication.targetFrameRateを変える方法よりも、入力の応答性という点でより良い選択になると考えられます。2
例として、入力がない間はフレームレートを落としておき、入力があったタイミングでフレームレートを上げて応答することを考えた際に下の違いがあります。

target_frame_rate_interaction.png

ondemand_rendering_interaction.png

あとは、シミュレーションや機械学習といったシチュエーションでも望まれていた機能ではないかと思います。
それらは実際はレンダリングを必要としないことがほとんどなので、この機能を活用してレンダリングにリソースを割かないようにすればより早く結果を得られると考えられます。

使用方法

制御はスクリプトから行います。
名前空間UnityEngine.RenderingOnDemandRenderingというクラスに3つのStaticなAPIが用意されています。

OnDemandRendering.renderFrameInterval

私たちが直接変更できる唯一のプロパティであり、これでレンダリングをおこなう間隔を設定します。
例えばこれに3を代入すれば、ゲームループの3フレーム中に1回レンダリングするようになります。(レンダリング更新頻度が1/3)

タッチ入力があるまで20[fps]にしておき、タッチがあったらそこから60[fps]にする例はこんな感じです。

OnDemandRenderingTest.cs
using UnityEngine;
using UnityEngine.Rendering;

public class OnDemandRenderingTest : MonoBehaviour
{
    private void Start()
    {
        QualitySettings.vSyncCount = 0;
        Application.targetFrameRate = 60;

        // 20 (= 60 / 3) fps
        OnDemandRendering.renderFrameInterval = 3;
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // 60 fps
            OnDemandRendering.renderFrameInterval = 1;
        }
    }
}

OnDemandRendering.effectiveFrameRate

現在の設定から想定されるレンダリングフレームレート値です。
例えばゲームループを60fpsで動かしている端末なら、通常はレンダリングも60fpsですが、renderFrameIntervalを3に設定しているときは20(=60 / 3)が返ってきます。

OnDemandRendering.willCurrentFrameRender

現在のゲームループフレームがレンダリング対象かを返します。

will_current_frame_render.png

これは何に使えるのか…ということですが、レンダリングにリソースを割かなければならないフレームかどうかが判断できるので、「見た目のフレームレートを安定させつつ、高負荷な処理を裏で回す」的なことに使えるっぽいです。
なかなか使う場面は限られそうですが、使い方のイメージとしてはこんな感じでしょうか。

OnDemandRenderingTest2.cs
using UnityEngine;
using UnityEngine.Rendering;

public class OnDemandRenderingTest2 : MonoBehaviour
{
    private void Update()
    {
        if (OnDemandRendering.willCurrentFrameRender)
        {
            // レンダリングするので重い処理はしない
        }
        else
        {
            // レンダリングしてないので重い処理を実行
        }
    }
}

おわりに

今回は特に検証などはしていないですが、上手に使えば高い効果が得られそうです。
モバイルアプリ開発なんかでは積極的に取り入れていきたい機能だと感じました。

参考


  1. オンデマンドは「要求に応じて」の意味。 

  2. そもそもApplicationクラスの値は頻繁に変えることになんか抵抗があります…。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32