NGUI製作背包等有大量物品圖片的界面時候如何優化Drawcall?
NGUI 在製作背包等有大量物品圖片的界面時候,因為物品一般會很多如果做成一個圖集肯定會非常大超過 2048*2048,所以覺得這不是一個好的辦法也不現實,如果是用 UITexture(每一個物品圖標保存一個texture) 的話又會增加很多 Drawcall,所以暫時還沒想到好的辦法。請問大家在考慮這樣問題的時候是怎麼解決怎麼優化的呢?或者有什麼好的建議么?
這個真是老大難問題了,困擾了很長時間,最後放大招自己開發了一套動態Batch系統。
思路是參考垃圾回收演算法的設計,把RenderTexture看成一個二維託管堆,需要一張小圖的時候就在上面分配一塊空間出來,然後把小圖渲染到上面,最後把RenderTexture和UV交給各種Renderer就可以了。
RenderTexture上的空間用引用計數管理,比如這個小圖的Renderer全都Disable了,就標記這塊空間可以重新利用,為了實現比較高的使用效率,分配演算法需要精心設計一下。
這麼做有幾個優點。
1. 增量修改Atlas,增加一個Sprite很簡單,只需要一個DrawTexture指令,不需要重新打包整個Atlas。
2. 速度快,RenderTexture靠GPU渲染,不需要來回copy pixel花好幾秒。3. 內存按需使用,不需要為了顯示幾個小圖把好幾個巨大的Atlas載入進來,一開始512x512,不夠用了就擴展成1024x1024。
4. 可以跨AssetBundle batch draw call。兩個AB裡面的圖可以batch到一個draw call里。5. 可以適配多種Renderer,只要是一個Shader,不管UGUI,NGUI,SpriteRenderer甚至MeshRenderer,都可以一個draw call渲染。缺點就是Atlas的layout不如靜態打包的緊湊。另外RenderTexture不能壓縮,但是這個還好,一是2D遊戲壓縮紋理顯示效果不理想,二是內存按需使用,即使不壓縮一般也壓力也比原來小。可以根據具體需求動態靜態配合使用。
這套基礎系統搞好了以後又做了一套component給做UI的人用,從此再也不用操心打包Atlas和draw call三明治的事了,開發直接上小圖。比如給背包的GameObject上加一個動態batch的component,這樣運行的時候如果背包內容變化了,自動就把小圖標batch到一個draw call里,然後釋放掉,圖標的draw call始終是1,內存也不會爆,design設計一萬種圖標也沒壓力,scalability非常好。大圖占內存,散圖耗Draw Call,動態圖集耗CPU。真是可憐……看來大家也沒什麼辦法了……
製作圖集主要是為了讓這個圖對應到一個材質(球),引擎對一個材質的東西會進行一次drawcall,這個是為什麼要用圖集的原理。對於你這個事情,規划出合理的分包吧。
我們是一個系統引用共有圖集(公用的按鈕,邊框等)和系統私有圖集。先拆開兩個圖集。設計時盡量用共有圖集的資源。一般圖集應該都是1024的吧,能支持2048了嗎
我覺得可以將物品分類做成不同的幾個圖集,每類物品做一個模板,用的時候根據物品的類型去複製不同的模板就行了。。
目前只有分好包 暫時沒有特別的方法 因為圖片量就擺在那 1024是主流 2048最好別用了
多幾個drawcall問題不大,反倒是合併離線圖集費內存,在線合併費CPU。
可以動態生成圖集。一張空白的Bitmap,只在運行時將你需要顯示的圖片打至其中,動態生成和更新紋理。
手動分多個1024*1024圖集,記下圖集中IconId的範圍,然後if
比如,A圖集是IconId從10000-13000的,B圖集是IconId從13001-15000的,那麼我要找13030的IconId的圖,肯定是要到B圖集里找呀..
推薦閱讀:
※遊戲的原版源代碼還在,資料片的丟失,想要復刻出資料片難度和工作量有多大?
※cocos2d-x為什麼大量使用宏定義函數,而不選擇使用模板?
※遊戲開發者怎麼讓玩家互相產生仇恨?
※「開局一個人一條狗一把槍,裝備全靠撿,一刀999級」 玩這類遊戲是怎樣的體驗?
※如何為Nintendo Switch開發遊戲?