動的解像度は、個々のレンダーターゲットを動的にスケーリングし、GPU の負荷を軽減できるカメラ設定です。アプリケーションのフレームレートが減少する場合は、徐々に解像度を下げて、一貫したフレームレートを維持することができます。アプリケーションが GPU にバインドされている結果、フレームレートが低下しそうなことをパフォーマンスデータが示すと、Unity はこのスケーリングを発動します。また、アプリケーションの特に GPU 負担が大きい部分を見越して、スクリプトを使ってスケーリングを制御することで、スケーリングを手動で発生させることもできます。徐々にスケーリングすると、動的解像度はほとんど目立つことはありません。
Unity は Xbox One、PS4、Nintendo Switch、iOS、macOS、tvOS (Metal のみ)、Android (Vulkanのみ)、Windows スタンドアロン、UWP (DirectX 12のみ) で動的解像度をサポートします。
動的な解像度では、Unity はレンダーターゲットを再割り当てしません。概念的には、Unity はレンダーターゲットをスケールします。ただし、実際には、Unity はエイリアシングを使用し、縮小されたレンダリングターゲットは、元のレンダーターゲットのほんの一部のみを使用します。Unity は、レンダーターゲットを完全な解像度で割り当てます。次に、動的解像度システムは、新しいターゲットを再割り当てする代わりに、元のターゲットの一部を使用してレンダリングターゲットをスケールダウンし、再度バックアップします。
動的な解像度では、レンダーターゲットには DynamicallyScalable フラグがあります。これを使って、このレンダーテクスチャを動的解像度処理の一部としてスケールするかどうかを設定します。カメラには allowDynamicResolution フラグもあります。これを使って動的解像度を設定すると、動的解像度をあまり複雑でないものに適用したい場合に、レンダーターゲットをオーバーライドする必要がありません。
カメラの Allow Dynamic Resolution を有効にすると、Unity はそのカメラのすべてのターゲットをスケールします。
スケールは ScalableBufferManager を通して制御できます。 ScalableBufferManager は、動的解像度システムがスケールするように設定したすべてのレンダーターゲットの動的な幅と高さのスケールを制御します。
例として、アプリケーションが望ましいフレームレートで実行されていると仮定してください。しかし、状況によってはパーティクルの増加、ポストエフェクト、画面の複雑さが組み合わされて GPU のパフォーマンスが低下する場合があります。Unity FrameTimingManager を使用すると、CPU や GPU のパフォーマンスが低下し始めたときに、それを検出できます。そのため、 FrameTimingManager
を使って希望の幅と高さのスケールを計算し、フレームレートを希望の範囲内に維持し、スケールをその値に落としてパフォーマンスを (即座に、または、徐々にフレームの設定された量に) 安定させます。画面の複雑さが減り、GPU が一貫して実行されている場合は、GPU が処理できる値に幅と高さのスケールを上げることができます。
このスクリプトサンプルは、API の基本的な使い方を示しています。シーン内のカメラに追加し、カメラ設定で Allow Dynamic Resolution をチェックしてください。また、Player 設定 (Edit> Project Settings から Player カテゴリを選択) を開き、Enable Frame Timing Stats チェックボックスをチェックする必要があります。
マウスをクリックするか、1 本の指で画面を軽くタップすると、高さと幅の解像度がそれぞれ scaleWidthIncrement
と scaleHeightIncrement
変数の値だけ下がります。2 本の指でタップすると同じ値で解像度が上がります。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DynamicResolutionTest : MonoBehaviour
{
public Text screenText;
FrameTiming[] frameTimings = new FrameTiming[3];
public float maxResolutionWidthScale = 1.0f;
public float maxResolutionHeightScale = 1.0f;
public float minResolutionWidthScale = 0.5f;
public float minResolutionHeightScale = 0.5f;
public float scaleWidthIncrement = 0.1f;
public float scaleHeightIncrement = 0.1f;
float m_widthScale = 1.0f;
float m_heightScale = 1.0f;
// 動的解像度のアルゴリズムの値。フレームをまたがって持続されます。
uint m_frameCount = 0;
const uint kNumFrameTimings = 2;
double m_gpuFrameTime;
double m_cpuFrameTime;
// 初期化に使用します
void Start()
{
int rezWidth = (int)Mathf.Ceil(ScalableBufferManager.widthScaleFactor * Screen.currentResolution.width);
int rezHeight = (int)Mathf.Ceil(ScalableBufferManager.heightScaleFactor * Screen.currentResolution.height);
screenText.text = string.Format("Scale: {0:F3}x{1:F3}\nResolution: {2}x{3}\n",
m_widthScale,
m_heightScale,
rezWidth,
rezHeight);
}
// Update はフレームごとに 1 回呼び出されます
void Update()
{
float oldWidthScale = m_widthScale;
float oldHeightScale = m_heightScale;
// 1 本指のタップは解像度を下げます
if (Input.GetButtonDown("Fire1"))
{
m_heightScale = Mathf.Max(minResolutionHeightScale, m_heightScale - scaleHeightIncrement);
m_widthScale = Mathf.Max(minResolutionWidthScale, m_widthScale - scaleWidthIncrement);
}
// 2 本指のタップは解像度を上げます
if (Input.GetButtonDown("Fire2"))
{
m_heightScale = Mathf.Min(maxResolutionHeightScale, m_heightScale + scaleHeightIncrement);
m_widthScale = Mathf.Min(maxResolutionWidthScale, m_widthScale + scaleWidthIncrement);
}
if (m_widthScale != oldWidthScale || m_heightScale != oldHeightScale)
{
ScalableBufferManager.ResizeBuffers(m_widthScale, m_heightScale);
}
DetermineResolution();
int rezWidth = (int)Mathf.Ceil(ScalableBufferManager.widthScaleFactor * Screen.currentResolution.width);
int rezHeight = (int)Mathf.Ceil(ScalableBufferManager.heightScaleFactor * Screen.currentResolution.height);
screenText.text = string.Format("Scale: {0:F3}x{1:F3}\nResolution: {2}x{3}\nScaleFactor: {4:F3}x{5:F3}\nGPU: {6:F3} CPU: {7:F3}",
m_widthScale,
m_heightScale,
rezWidth,
rezHeight,
ScalableBufferManager.widthScaleFactor,
ScalableBufferManager.heightScaleFactor,
m_gpuFrameTime,
m_cpuFrameTime);
}
// 必要に応じて、次のフレーム時間を見積もり、解像度スケールを更新します
private void DetermineResolution()
{
++m_frameCount;
if (m_frameCount <= kNumFrameTimings)
{
return;
}
FrameTimingManager.CaptureFrameTimings();
FrameTimingManager.GetLatestTimings(kNumFrameTimings, frameTimings);
if (frameTimings.Length < kNumFrameTimings)
{
Debug.LogFormat("Skipping frame {0}, didn't get enough frame timings.",
m_frameCount);
return;
}
m_gpuFrameTime = (double)frameTimings[0].gpuFrameTime;
m_cpuFrameTime = (double)frameTimings[0].cpuFrameTime;
}
}
2018–09–20 公開ページ
動的解像度に関するドキュメントは 2017.4 で追加
macOS (Metal のみ)、Windows スタンドアロン、UWP (DirectX 12 のみ) 用の動的解像度のサポートは 2019.1 で追加
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.