Managing automatic quality based on current FPS

We have a game that is a high quality 3D mobile game. As such, some mobile devices struggle to run it. Thus, there are 3 quality levels. (Low, normal, high) Many devices, particularly older ones such as androids, struggle on normal quality (the default setting). Thus we decided the add a quality controller that samples the fps, for some intervals, determines the average, and changes to quality level to low if the fps is lower than a set amount.

We wanted to post this script, and get some feedback about it, as well as any other ways to go about doing this. Currently the script will run every time the application is started, and it samples the first 5 fps readings, and disregards the first. If the average fps is lower than 26 the quality is changed. Any feedback/thoughts are greatly appreciated!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class QualityController : MonoBehaviour
{
    // Start is called before the first frame update
    private static QualityController instance;
    private static readonly int FPS_QUALITY_SWITCH_VALUE = 26;

    private int counter;
    private float pollingTime = 1;
    private float frameCounter;
    private float time;
    private int currentFPS;

    private List<int> fpsTracker;

    void Start()
    {
        if (instance == null) {
            // if no instance exists
            DontDestroyOnLoad(gameObject);
            fpsTracker = new();
            instance = this;
            print("[QUALITY CONTROLLER]: Did set instance.");
        } else {
            // destroy
            print("[QUALITY CONTROLLER]: Instance exists, will destroy!");
            Destroy(gameObject);
        }
    }

    // Update is called once per frame
    void Update()
    {
        // increment frames
        frameCounter += 1;
        // get time elapsed
        time += Time.deltaTime;
        // calculate fps
        if (time >= pollingTime) {

            counter ++;

            currentFPS = Mathf.RoundToInt(frameCounter / time);
            print("[QUALITY CONTROLLER]: Current FPS - "+currentFPS);

           
            if (counter != 1) {
                // skip first
                fpsTracker.Add(currentFPS);

                if (counter == 5) {
                    RunQualityCheck();
                }
            }

            time -= pollingTime;
            frameCounter = 0;
        }
    }

    void RunQualityCheck() {

        print("[QUALITY CONTROLLER]: Running initial quality check...");

        int total = 0;

        foreach(int i in fpsTracker) {
            // count all frame sampled
            total += i;
        }

        // calculate average fps
        float averageFPS = total / fpsTracker.Count;

        print("[QUALITY CONTROLLER]: total frames: "+total+", sampled: "+fpsTracker.Count+", AVERAGE FPS: "+averageFPS);

        if (averageFPS < FPS_QUALITY_SWITCH_VALUE) {
            print("[QUALITY CONTROLLER]: Lowering quality!");
            // change quality to low, 0
            GameAdmin.SetQuality(0);
            // Look for a settings manager, if it exists update the UI
            var settingsManager = GameObject.FindObjectOfType<SettingsManager>();
            // if it exists update it
            if (settingsManager != null) {
                print("[QUALITY CONTROLLER]: will update settings manager");
                settingsManager.initialize();
            }
        }
    }
}

Anyone have any thoughts on this? Would like feedback before it is pushed in the next update :slight_smile: