【Unity優化】概要

【參考原文】Unity3D之優化(待續)
【參考原文】Unity中的優化技術

代碼層面

  1. foreach
    Mono下的foreach使用需謹慎。頻繁調用容易觸及堆上限,導致GC過早觸發,出現卡頓現象。
    特別注意的是在Update裏面如果非必要,不要使用foreach。儘可能用for來代替foreach。會產生GC Alloc,說明foreach調用GetEnumerator()時候有堆內存上的操作,new和dispose
  2. string 修改
    每次使用string的時候,都要在內存裏面創建一個新的字符串對象,就需要爲該對象分配新的空間。
    特別在循環中需要修改string對象的時候,會頻繁的分配新的空間。推薦使用StringBuilder.Append等操作來處理。
  3. gameObject.tag
    gameObject.tag會在內部循環調用對象分配的標籤屬性以及拷貝額外的內存,推薦使用
    gameObject.CompareTag(“XXX”)來代替.tag
  4. 使用ObjectPool對象池來避免頻繁Insatnce,Destory

框架設計層面

一個相對中大型的遊戲,系統非常的多。這時候合理的適時的釋放內存有助於遊戲的正常體驗,甚至可以防止內存快速到達峯值,導致設備Crash。
目前主流平臺機型可用內存:
Android平臺:在客戶端最低配置以上,均需滿足以下內存消耗指標(PSS):

  1. 內存1G以下機型:最高PSS<=150MB
  2. 內存2G的機型:最高PSS<=200MB
    iOS平臺:在iPhone4S下運行,消耗內存(real mem)不大於150MB
    1.場景切換時避開峯值。
    當前一個場景還未釋放的時候,切換到新的場景。這時候由於兩個內存疊加很容易達到內存峯值。解決方案是,在屏幕中間遮蓋一個Loading場景。在舊的釋放完,並且新的初始化結束後,隱藏Loading場景,使之有效的避開內存大量疊加超過峯值。
    2.GUI模塊加入生命週期管理。
    主角、強化、技能、商城、進化、揹包、任務等等。通常一個遊戲都少不了這些系統。但要是全部都打開,或者這個時候再點世界地圖,外加一些邏輯數據內存的佔用等等。你會發現,內存也很快就達到峯值。

這時候有效的管理系統模塊生命週期就非常有必要。首先將模塊進行劃分:

1)經常打開 Cache_10;

2)偶爾打開 Cache_5;

3)只打開一次 Cache_0。

創建一個ModuleMananger 類,內部Render方法每分鐘輪詢一次。如果是“Cache_0”這個類型,一關閉就直接Destroy釋放內存;“Cache_10”這個類型爲10分鐘後自動釋放內存;” Cache_5”這種類型爲5分鐘後自動釋放內存。每次打開模塊,該模塊就會重新計時。這樣就可以有效合理的分配內存。

貼圖層面

代碼上的內存優化,很大層面上都不及貼圖上的優化。有時候改一張圖就幫你省了大幾兆的內存。
1.巧妙通過調整紋理資源,來調整圖的大小。比如:通過9宮格、部分縮小後Unity裏在拉大等方式。
比如:(主要調整了兩個小元素)就省了一半的內存。
優化前:
這裏寫圖片描述

優化後:
這裏寫圖片描述

2.Ios平臺使用PVRT壓縮紋理。Adroid平臺使用ETC1格式壓縮。均可以減至1/4的內存大小。優化非常明顯。
目前主流的Android機型基本都支持ETC1格式壓縮。但ETC1只能支持非Alpha通道的圖片壓縮。所以一般把Alpha通道圖分離出來,繪製到GPU顯存時,a值從Alpha圖裏獲取,無Alpha通道的圖就可以使用ETC1壓縮。

而ETC2以上的格式壓縮雖然支持含Alpha通道的圖片,但是支持的機型還比較少。目前不推薦使用。
這裏寫圖片描述
未使用ETC1壓縮前的內存佔用大小1024*1024的png圖佔用10.7M( 包含了Editor中的內存佔用,以及mip map內存佔用 )。

mipMap是攝像機離得遠近用不同的圖片,3D遊戲中用內存換性能的一種有效方式。它會將大圖變成若干小圖,存儲內存中,當攝像機離的比較遠的時候,只需使用小圖。
UI、2D場景可以把Texure這個設置去掉。
這裏寫圖片描述
這樣實際遊戲中未壓縮紋理1024×1024的圖在內存中佔用是 4M。(Unity Profiler下看應該是8M)
這裏寫圖片描述
使用ETC1壓縮後,場景圖片一張大小隻有1.3MB,加上通道圖2.6M。幾乎是用來的1/4。
這裏寫圖片描述
甚至文件的大小也小了1/4。

3.通過減色的方式減少圖片大小。很多UI其實使用的色彩很少,用不到256色。這類圖片就可以進行減色壓縮。
這裏寫圖片描述

優化總結

  1. 更新不透明貼圖的壓縮格式爲ETC 4bit,因爲android市場的手機中的GPU有多種,
    每家的GPU支持不同的壓縮格式,但他們都兼容ETC格式,

  2. 對於透明貼圖,我們只能選擇RGBA 16bit 或者RGBA 32bit。

  3. 減少FPS,在ProjectSetting-> Quality中的
    VSync Count 參數會影響你的FPS,EveryVBlank相當於FPS=60,EverySecondVBlank = 30;
    這兩種情況都不符合遊戲的FPS的話,我們需要手動調整FPS,首先關閉垂直同步這個功能,然後在代碼的Awake方法裏手動設置FPS(Application.targetFrameRate = 45;)
    降低FPS的好處:
    1)省電,減少手機發熱的情況;
    2)能都穩定遊戲FPS,減少出現卡頓的情況。

  4. 當我們設置了FPS後,再調整下Fixed timestep這個參數,
    這個參數在ProjectSetting->Time中,目的是減少物理計算的次數,來提高遊戲性能。

  5. 儘量少使用Update LateUpdate FixedUpdate,這樣也可以提升性能和節省電量。
    多使用事件(不是SendMessage,使用自己寫的,或者C#中的事件委託)。

  6. 待機時,調整遊戲的FPS爲1,節省電量。

  7. 圖集大小最好不要高於1024,否則遊戲安裝之後、低端機直接崩潰、原因是手機系統版本低於2.2、超過1000的圖集無法讀取、導致。
    2.2 以上沒有遇見這個情況。
    注意手機的RAM 與 ROM、小於 512M的手機、直接放棄機型適配。

VSCount 垂直同步

unity3d中新建一個場景空的時候,幀速率(FPS總是很低),大概在60~70之間。
一直不太明白是怎麼回事,現在基本上明白了。我在這裏解釋一下原因,如有錯誤,歡迎指正。
在Unity3D中當運行場景打開Profiler的時候,我們會看到VSync 這一項佔了很大的比重。
這個是什麼呢,這個就是垂直同步,稍後再做解釋。
我們可以關閉VSync來提高幀速率,選擇edit->project settings->Quality。在右側面板中可以找到VSync Count,把它選成Don’t Sync。
這裏寫圖片描述
這就關閉了VSync(垂直同步),現在在運行場景看看,幀速率是不是提高很多。

現在來說說什麼是垂直同步,要知道什麼是垂直同步,必須要先明白顯示器的工作原理,
顯示器上的所有圖像都是一線一線的掃描上去的,無論是隔行掃描還是逐行掃描,
顯示器都有兩種同步參數——水平同步和垂直同步。

什麼叫水平同步?什麼叫垂直同步?
垂直和水平是CRT中兩個基本的同步信號,水平同步信號決定了CRT畫出一條橫越屏幕線的時間,
垂直同步信號決定了CRT從屏幕頂部畫到底部,再返回原始位置的時間,
而恰恰是垂直同步代表着CRT顯示器的刷新率水平。

爲什麼關閉垂直同步信號會影響遊戲中的FPS數值?
如果我們選擇等待垂直同步信號(也就是我們平時所說的垂直同步打開),
那麼在遊戲中或許強勁的顯卡迅速的繪製完一屏的圖像,但是沒有垂直同步信號的到達,
顯卡無法繪製下一屏,只有等85單位的信號到達,纔可以繪製。
這樣FPS自然要受到操作系統刷新率運行值的制約。

而如果我們選擇不等待垂直同步信號(也就是我們平時所說的關閉垂直同步),那麼遊戲中作完一屏畫面,
顯卡和顯示器無需等待垂直同步信號就可以開始下一屏圖像的繪製,自然可以完全發揮顯卡的實力。
但是不要忘記,正是因爲垂直同步的存在,才能使得遊戲進程和顯示器刷新率同步,使得畫面更加平滑和穩定。
取消了垂直同步信號,固然可以換來更快的速度,但是在圖像的連續性上勢必打折扣。
這也正是很多朋友抱怨關閉垂直後發現畫面不連續的理論原因。

合併材質球

unity 3d中每倒入一次模型就多一個材質球,可我的這些模型都是共用一張貼圖的就想共用一個材質球,所以每次都要刪除再附上,很麻煩。怎麼才能合併這些材質球?
採用TexturePacking吧
1、遍歷gameobject,取出material,並根據shader來將material分類
2、調用Unity自帶的PackTextures函數來合併每個shader分類中的material所對應的textures(PackTextures函數有缺陷,不過可以將就用)
3、根據合併的大的texture來更新原有模型的texture、material已經uv座標值。

需要注意的是:需要合併的紋理應該是物體在場景中距離相近的,如果物體在場景中的距離較遠,
則不建議合併紋理,因爲這樣做很有可能非但起不到優化的作用,反而降低了運行效率。

mesh合併

分爲2種方式合併
1.自帶的合併必須勾選靜態
這裏寫圖片描述
所有被勾選了“Static”的GameObject,其中的Mesh Filter中的mesh都會被合併到 “Combined Mesha (root: scene)” 中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章