幀率低的奇怪問題
在優化游戲的時候遇到了一個奇怪的問題,經過一輪的優化之后,游戲的CUP占用率和內存使用都在正常范圍(用騰訊cube 或者UWA),在profile 中也沒有毛刺,在部分android手機上能流暢運行。
但是在某些大屏幕的手機上FPS特別低,在一部4核心CUP、4G內存的Oppo手機上幀率不到23FPS ,但是在小米2上運行反而特別流暢。
進過一系列的排查和試驗,某些標榜為高端機的手機,手機屏幕特別大,CUP和內存參數還不錯,但是手機的GPU特別差(GPU參數一般不會標出來)。對於大屏的手機比如1080p的,每一幀要處理的像素特別多,但是GPU性能不足以處理這么多像素,結果就造成了幀率特別的低的問題。
解決
最直接的方法就是修改游戲的渲染分辨率,手機幀率低的時候,直接改低游戲的渲染分辨率,減少每一幀要處理的像素數量。
unity 提供了一個方法設置渲染分辨率
Screen.SetResolution(designWidth,designHeight,true);
這里的做法是簡單的把渲染分辨率設置成設計分辨率。如果手機本身的分辨率低於設計分辨率就不要再修改了。
#if UNITY_ANDROID int scWidth = Screen.width; int scHeight = Screen.height; int designWidth=720; //這個是設計分辨率 int designHeight=1280; if( scWidth<=designWidth || scHeight<=designHeight) return; Screen.SetResolution(designWidth,designHeight,true); #endif
模糊問題
降低渲染分辨率當然能過提高幀率,但是也會使得真正大屏幕的高端機(GPU性能高)的游戲畫面變得模糊。這個時候需要判斷什么時候才能使用分辨率設置。
一個簡單的辦法就是判斷平均FPS, 如果最近15幀的平均FPS低於25,就降低渲染分辨率。有點簡單粗暴了。
private float f_UpdateInterval = 0.5F; private float f_LastInterval; private int i_Frames = 0; private float f_Fps; private const int fpsArrayLen=8; private float[] fpsArray = new float[fpsArrayLen]; private int fpsIndex=0; private const int standardFPS=26; /* 再update 中執行,每隔0.5秒計算一次FPS*/ void FPSUpdate() { ++i_Frames; if (Time.realtimeSinceStartup > f_LastInterval + f_UpdateInterval) { f_Fps = i_Frames / (Time.realtimeSinceStartup - f_LastInterval); i_Frames = 0; f_LastInterval = Time.realtimeSinceStartup; fpsArray[fpsIndex]=f_Fps; fpsIndex=(++fpsIndex)%fpsArrayLen; } } /*判斷時候達到了標准的FPS*/ private bool IsStandFPS() { float totalFPS=0; for(int i=0;i<fpsArray.Length;++i) { totalFPS+=fpsArray[i]; } float averageFPS = totalFPS/fpsArray.Length; if(averageFPS <standardFPS) { return false; } return true; }
以上代碼中,需要在update 函數中調用FPSUpdate 就算FPS。 在游戲加載結束之后再4秒再調用IsStandFPS(), 如果幀率低於設定的標准,就需要降低渲染分辨率了。 游戲加載過程中會造成卡幀,所以建議加載結束后4秒在做判斷。