본문으로 바로가기

Unity FPSCounter

category Technical Report/Unity 2017. 7. 26. 10:40
반응형

using UnityEngine;
using UnityEngine.UI; // Text를 사용할 경우 필요

public class FPSDisplay : MonoBehaviour
{
    [Header("Display Settings")]
    [SerializeField] private bool useTextComponent = true;
    [SerializeField] private Text fpsText; // Canvas용 Text 컴포넌트

    private float deltaTime;

    private void Start()
    {
        if (useTextComponent && fpsText == null)
        {
            fpsText = GetComponent<Text>();
            if (fpsText == null)
            {
                Debug.LogWarning("FPSDisplay: Text component not found!");
                useTextComponent = false;
            }
        }
    }

    private void Update()
    {
        // FPS 계산 (지수평활 이동평균)
        deltaTime += (Time.deltaTime - deltaTime) * 0.1f;
    }

    private void OnGUI()
    {
        if (useTextComponent) return; // Text 모드일 땐 OnGUI를 스킵

        int w = Screen.width, h = Screen.height;
        GUIStyle style = new GUIStyle
        {
            alignment = TextAnchor.UpperLeft,
            fontSize = h * 2 / 100,
            normal = { textColor = new Color(0f, 0.5f, 1f, 1f) }
        };

        Rect rect = new Rect(10, 10, w, h * 2 / 100);
        string text = GetFormattedFPS();
        GUI.Label(rect, text, style);
    }

    private void LateUpdate()
    {
        if (!useTextComponent || fpsText == null) return;

        fpsText.text = GetFormattedFPS();
    }

    private string GetFormattedFPS()
    {
        float msec = deltaTime * 1000f;
        float fps = 1f / deltaTime;
        return $"{msec:0.0} ms ({fps:0.} fps)";
    }
}

 

FPSCounter.cs


using UnityEngine;

public class FPSCounter : MonoBehaviour
{
    public static FPSCounter Instance;

    private float deltaTime;

    public float FPS => 1.0f / Mathf.Max(deltaTime, 0.0001f);

    private void Awake()
    {
        if (Instance == null) Instance = this;
        else Destroy(gameObject);
    }

    private void Update()
    {
        deltaTime += (Time.deltaTime - deltaTime) * 0.1f;
    }
}

 

URP Render Feature


using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class FPSOverlayFeature : ScriptableRendererFeature
{
    class FPSOverlayPass : ScriptableRenderPass
    {
        private GUIStyle style;

        public FPSOverlayPass()
        {
            renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
            style = new GUIStyle
            {
                fontSize = 24,
                normal = { textColor = Color.yellow }
            };
        }

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            if (Application.isPlaying)
            {
                CommandBuffer cmd = CommandBufferPool.Get("FPS Overlay");

                using (new UnityEngine.Rendering.ProfilingScope(cmd, new ProfilingSampler("FPSOverlayPass")))
                {
                    float fps = FPSCounter.Instance != null ? FPSCounter.Instance.FPS : 0f;
                    string fpsText = $"{fps:0.} FPS";

                    // 화면에 텍스트 출력
                    // UnityEngine.GUI를 사용할 수는 없으니 DebugOverlay API 사용
                    DebugOverlay.AddOverlayText(fpsText, new Vector2(10, 10), style);
                }

                context.ExecuteCommandBuffer(cmd);
                CommandBufferPool.Release(cmd);
            }
        }
    }

    FPSOverlayPass _pass;

    public override void Create()
    {
        _pass = new FPSOverlayPass();
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(_pass);
    }
}
반응형