ScalableBufferManager를 통해 스케일을 제어할 수 있습니다. ScalableBufferManager를 사용하면 다이내믹 해상도 시스템을 확대/축소하기 위해 표시한 모든 렌더 타겟의 동적 너비와 높이 스케일을 제어할 수 있습니다.
예를 들어 애플리케이션이 적절한 프레임 속도로 실행 중이지만, 일부 상황에서 파티클 증가, 사후 효과, 화면 복잡도 등으로 인해 GPU 성능이 저하된다고 가정해 보겠습니다. Unity FrameTimingManager를 사용하면 CPU 또는 GPU 성능이 저하되는 시점을 감지할 수 있습니다. 따라서 FrameTimingManager를 사용하여 원하는 새로운 너비와 높이 스케일을 계산해서 프레임 속도를 원하는 범위 내로 유지하고 스케일을 해당 값으로 내려 성능을 안정적으로 유지할 수 있습니다(정해진 프레임 수에 걸쳐 즉시 또는 점진적으로). 화면 복잡도가 감소하고 GPU의 성능이 일관되면 너비와 높이 스케일을 GPU가 처리할 수 있다고 계산한 값으로 다시 높일 수 있습니다.
이 예제 스크립트는 API의 기본적인 사용 방식을 보여 줍니다. 이를 씬의 카메라에 추가하고 Camera 설정에서 Allow Dynamic Resolution 을 선택합니다. 또한 Player 설정을 열고(메뉴: Edit > Project Settings 를 선택한 다음 Player 카테고리 선택) Enable Frame Timing Stats 체크박스를 선택해야 합니다. Enable Frame Timing Stats 프로퍼티의 기능에 대한 자세한 내용은 FrameTimingManager를 참조하십시오.
마우스를 클릭하거나 한 손가락으로 화면을 누르면 각각 scaleWidthIncrement 및 scaleHeightIncrement 변수의 값만큼 높이 및 너비 해상도가 낮아집니다. 두 손가락으로 누르면 해상도가 동일한 증분만큼 증가합니다.
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;
// Variables for dynamic resolution algorithm that persist across frames
uint m_frameCount = 0;
const uint kNumFrameTimings = 2;
double m_gpuFrameTime;
double m_cpuFrameTime;
// Use this for initialization
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 is called once per frame
void Update()
{
float oldWidthScale = m_widthScale;
float oldHeightScale = m_heightScale;
// One finger lowers the resolution
if (Input.GetButtonDown("Fire1"))
{
m_heightScale = Mathf.Max(minResolutionHeightScale, m_heightScale - scaleHeightIncrement);
m_widthScale = Mathf.Max(minResolutionWidthScale, m_widthScale - scaleWidthIncrement);
}
// Two fingers raises the resolution
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);
}
// Estimate the next frame time and update the resolution scale if necessary.
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;
}
}