123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- using System;
- using UnityEngine;
- namespace XGame.Framework.Quality
- {
- public class QualityModule : IQualityModule, IDisposable
- {
- private XQualityLevel _recommendQuality;
- public XQualityLevel RecommendQuality { get { return _recommendQuality; } }
- private XQualityLevel _curQuality;
- public XQualityLevel CurQuality { get { return _curQuality; } set { if (value != _curQuality) ChangeQualityLevel(value); } }
- public Action<XQualityLevel> OnQualityLevelChanged { get; set; }
- private Vector2Int _originalScreenSize;
- private const string SaveCurQualityKey = "CurQuality";
- //private static IQualityModule _instance;
- //public static IQualityModule Instance
- //{
- // get
- // {
- // if (_instance == null) _instance = new QualityModule();
- // return _instance;
- // }
- //}
- public QualityModule()
- {
- _originalScreenSize = new Vector2Int(Screen.width, Screen.height);
- _curQuality = (XQualityLevel)PlayerPrefs.GetInt(SaveCurQualityKey, (int)XQualityLevel.UnKnow);
- CalcRecommendQuality();
- InnerReset();
- if (MacroDefine.IsEditor) Application.targetFrameRate = 60;
- else
- {
- Application.targetFrameRate = _curQuality == XQualityLevel.UltraHD ? 60 : 30;
- }
- Log.Info($"设备推荐的游戏品质:{_recommendQuality},用户设置的游戏品质:{_curQuality}");
- }
- float IQualityModule.GetScreenScale()
- {
- return Screen.width * 1f / _originalScreenSize.x;
- }
- private float RecommendScreenScale(XQualityLevel level)
- {
- var scale = 1f;
- if (MacroDefine.IsAndroid)
- {
- switch (level)
- {
- case XQualityLevel.High:
- scale = 0.8f;
- break;
- case XQualityLevel.Medium:
- scale = 0.7f;
- break;
- case XQualityLevel.Low:
- scale = 0.7f;
- break;
- }
- }
- else if (MacroDefine.IsiOS)
- {
- switch (level)
- {
- case XQualityLevel.High:
- case XQualityLevel.Medium:
- scale = 0.8f;
- break;
- case XQualityLevel.Low:
- scale = 0.7f;
- break;
- }
- }
- return scale;
- }
- /// <summary>
- /// 判断是否模拟器函数
- /// 通常Android才有模拟器
- /// 模拟器可以模拟很多传感器信息
- /// 此处选用光传感器判断
- /// 实测雷电模拟器,夜神模拟器,网易mumu,腾讯手游助手都成功判断为模拟器
- /// </summary>
- /// <returns>是否模拟器</returns>
- private static bool IsSimulator()
- {
- #if UNITY_ANDROID
- try
- {
- AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
- AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
- AndroidJavaObject sensorManager = currentActivity.Call<AndroidJavaObject>("getSystemService", "sensor");
- AndroidJavaObject sensor = sensorManager.Call<AndroidJavaObject>("getDefaultSensor", 5); //光传感器
- return sensor == null;
- }
- catch (Exception e)
- {
- return false;
- }
- #endif
- return false;
- }
- private void CalcRecommendQuality()
- {
- //显存
- int graphicsMemorySize = SystemInfo.graphicsMemorySize;
- //内存
- int systemMemorySize = SystemInfo.systemMemorySize;
- //cpu核心数
- int cpuCount = SystemInfo.processorCount;
- //cpu频率
- int cpuFrequency = SystemInfo.processorFrequency;
-
- if (MacroDefine.IsEditor)
- {
- _recommendQuality = XQualityLevel.UltraHD;
- }
- else if (MacroDefine.IsAndroid)
- {
- //模拟器
- if (IsSimulator())
- {
- _recommendQuality = XQualityLevel.High;
- }
- //分辨率低于1344,4核心以下,主频低于1.5GHz,内存低于2GB,一律视为低端机
- else if (Math.Max(_originalScreenSize.x, _originalScreenSize.y) < 1344 || cpuCount < 4 || cpuFrequency < 1500 || systemMemorySize <= 2048)
- {
- _recommendQuality = XQualityLevel.Low;
- }
- // 6核,内存4G,显存达到2G 高配
- else if (cpuCount >= 6 && systemMemorySize > 3072 && graphicsMemorySize >= 2048)
- {
- _recommendQuality = XQualityLevel.High;
- }
- else
- {
- _recommendQuality = XQualityLevel.Medium;
- }
- }
- else if (MacroDefine.IsiOS)
- {
- //iphone 8s以上
- if (SystemInfo.systemMemorySize > 2048)
- {
- _recommendQuality = XQualityLevel.High;
- }
- else
- {
- _recommendQuality = XQualityLevel.Medium;
- }
- }
- else
- {
- _recommendQuality = XQualityLevel.High;
- }
- if (_curQuality == XQualityLevel.UnKnow)
- ChangeQualityLevel(_recommendQuality);
- }
- private void ChangeQualityLevel(XQualityLevel ql)
- {
- // 保存
- _curQuality = ql;
- PlayerPrefs.SetInt(SaveCurQualityKey, (int)_curQuality);
- // 内部逻辑设置
- InnerReset();
- // 外部逻辑设置
- OnQualityLevelChanged?.Invoke(ql);
- Log.Info($"游戏品质等级切换到:{_curQuality}");
- }
- private void InnerReset()
- {
- // 引擎设置
- QualitySettings.SetQualityLevel((int)_curQuality);
- // 分辨率设置
- ResetResolution();
- // ShaderLod设置
- Shader.globalMaximumLOD = _curQuality.ShaderLodLevel();
- }
- // 分辨率设置
- private void ResetResolution()
- {
- if (MacroDefine.IsEditor)
- return;
- if (MacroDefine.IsAndroid || MacroDefine.IsiOS)
- {
- //var refSize = new Vector2Int(1920, 1080);
- var refLength = 1080;
- var scale = RecommendScreenScale(_curQuality);
- if (Screen.orientation == ScreenOrientation.Portrait || Screen.orientation == ScreenOrientation.PortraitUpsideDown)
- {
- //竖屏
- var width = (int)(refLength * scale);
- if (width >= _originalScreenSize.x)
- {
- width = _originalScreenSize.x;
- }
- if (width != Screen.width)
- {
- var height = (int)(width * _originalScreenSize.y * 1f / _originalScreenSize.x);
- Screen.SetResolution(width, height, Screen.fullScreen);
- }
- }
- else
- {
- //横屏
- var height = (int)(refLength * scale);
- if (height >= _originalScreenSize.y)
- {
- height = _originalScreenSize.y;
- }
- if (height != Screen.height)
- {
- var width = (int)(height * _originalScreenSize.x * 1f / _originalScreenSize.y);
- Screen.SetResolution(width, height, Screen.fullScreen);
- }
- }
-
- }
- }
- void IDisposable.Dispose()
- {
- if (OnQualityLevelChanged != null)
- {
- OnQualityLevelChanged = null;
- }
- }
- }
- }
|