using System; using System.Collections.Generic; using UnityEngine; using OHM.UnityToolkit; public class PerformanceManager : UniqueInstance { public enum QualityLevelType { AUTO = 0, MANUAL = 1 } [Serializable] public class QualityLevel { public int engineQualityLevel; public float fixedTimeStep = 0.01f; } public List qualityLevels; private AppController _app; public float refreshRate = 1f; public float criticalFpsThreashold; public float lowerQualityCriticalCount = 5f; private int _frameCount; private float _timeAccum; private int _criticalCount; public int QualityIndex { get; private set; } = -1; public QualityLevelType LevelType { get; private set; } public bool RecordPerformances { get; private set; } public float LastAverageFps { get; set; } = 60f; public event Action OnQualityChange; public event Action OnRecordingChange; protected override void AwakeInstance() { base.AwakeInstance(); LevelType = QualityLevelType.AUTO; if (qualityLevels != null && qualityLevels.Count > 0) { ApplyQuality(qualityLevels.Count - 1); } } private void Start() { _app = GetComponentInParent(); if (_app == null) { return; } _app.coreGame.onGameStarted.AddListener(StartRecord); _app.coreGame.onGameOver.AddListener(StopRecord); } private void StopRecord() { SetRecordPerformances(record: false); _criticalCount = 0; } private void StartRecord() { SetRecordPerformances(record: true); } private void ApplyQuality(int index) { if (QualityIndex == index) { return; } QualityIndex = index; QualityLevel level = qualityLevels[index]; Time.fixedDeltaTime = level.fixedTimeStep; QualitySettings.SetQualityLevel(level.engineQualityLevel, applyExpensiveChanges: true); if (this.OnQualityChange != null) { this.OnQualityChange(); } } public void ForceQuality(int index) { LevelType = QualityLevelType.MANUAL; ApplyQuality(index); } public void SetAutoQuality() { LevelType = QualityLevelType.AUTO; if (qualityLevels != null && qualityLevels.Count > 0) { ApplyQuality(qualityLevels.Count - 1); } } private void Update() { UpdatePerformances(); } public void SetRecordPerformances(bool record) { RecordPerformances = record; if (this.OnRecordingChange != null) { this.OnRecordingChange(); } _criticalCount = 0; } private void UpdatePerformances() { if (!RecordPerformances || LevelType != QualityLevelType.AUTO) { _criticalCount = 0; return; } if (QualityIndex < 1) { return; } _frameCount++; _timeAccum += Time.unscaledDeltaTime; if (_timeAccum <= refreshRate) { return; } LastAverageFps = _frameCount / _timeAccum; OnNewPerfValue(); } private void OnNewPerfValue() { _frameCount = 0; _timeAccum = 0f; if (LastAverageFps >= criticalFpsThreashold) { _criticalCount = 0; return; } _criticalCount++; if (_criticalCount >= lowerQualityCriticalCount) { LowerQuality(); _criticalCount = 0; } } private void LowerQuality() { int index = QualityIndex - 1; ApplyQuality(index); Debug.Log("Lowering quality to " + index); } }