Unity 6.3
0 онлайн 3 гостей 3 в системе
Вход

Контроль масштабирования с динамической разрешающей способностью

Масштабом можно управлять через ScalableBufferManager. Объект ScalableBufferManager позволяет управлять динамическим масштабом ширины и высоты всех целей рендеринга, помеченных для масштабирования системой динамического разрешения.

В качестве примера, предположим, что ваше приложение работает с желаемой частотой кадров, но при некоторых обстоятельствах производительность GPU снижается, из-за комбинации увеличенных частиц, пост-эффектов и сложности экрана. Unity FrameTimingManager позволяет вам определить, когда производительность CPU или GPU начинает снижаться. Таким образом, вы можете использовать FrameTimingManager для вычисления нового желаемого масштаба ширины и высоты, чтобы сохранить частоту кадров в желаемом диапазоне, и привести масштаб вниз до этого значения, чтобы сохранить производительность стабильной (либо мгновенно, либо постепенно в течение установленного количества кадров). Когда сложность экрана снижается и GPU работает последовательно, вы можете затем повысить масштаб ширины и высоты обратно до значения, которое вы рассчитали, что GPU может обрабатывать.

Пример

Этот примерный скрипт демонстрирует базовое использование свойства API.. Добавьте его к Camera в вашем Scene, и отметьте Разрешить Динамическое Разрешение в настройках Camera. Также необходимо открыть настройки Игрок (меню: Edit > Project Settings, затем выберите категорию Игрок) и отметить флажок 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;
    }
}