成長,也許從來都不是一件容易的事兒。
內存優化
圖形學、渲染優化
AssetBundle資源加載和卸載 Done
socket編程 (三次握手、四次揮手)
狀態機
C#高級特性 (閉包和匿名函數的區別)
lua編程 emergency
閉包和匿名函數的區別:
解釋1: 閉包是指有權訪問另一個函數作用域中的變量的函數。
解釋2:閉包是一個函數和該函數被定義時的詞法環境的組合,一個函數的返回值是一個函數引用,外部調用這個函數的引用時,需要堆棧中保留函數執行的變量環境,這種關係就叫做閉包。
匿名函數,一般用到匿名函數的時候都是立即執行的。通常叫做自執行匿名函數或者自調用匿名函數。常用來構建沙箱模式,作用是開闢封閉的變量作用域環境,
閉包跟函數是否匿名沒有直接關係,匿名函數和具名函數都可以創建閉包。
Unity5.X的AB機制
http://www.cnblogs.com/murongxiaopifu/p/5629415.html#autoid-3-3-0
ChunkBasedCompression 新增LZ4進行壓縮,加載時不需要加載整個AB,只加載對應數據塊兒。
新增Manifest清單文件記錄AB依賴關係,不必要再需要人爲的處理PopAssetDependencies/PushAssetDependencis
AB壓縮格式:
Lzma 默認的ab壓縮格式,壓縮比很高,但是加載時需要整個加載ab文件,會影響運行時加載速度,形成較大的內存開銷。
不壓縮,不壓縮的AB加載速度快,但是體積大。
Lz4時5.3版本之後新增的壓縮選項,壓縮比沒有lzma高,但優點在於加載時不需要整個加載AB,因此在加載速度和內存上有較大優勢。
隨包的AB建議lz4壓縮,兼顧文件大小和加載速度,網絡更新的ab建議lzma壓縮,高壓縮比可以減少數據流量。
www(url)的加載方式,加載完成後會在內存中創建較大的webStream,通常爲原AB大小的3-5倍,便於後續加載直接從內存加載。
www.loadFromCacheOrDownload()改方法的優勢在於能將解壓縮之後的ab文件存入磁盤作爲緩存,只會在內存中創建較小的serilizedFile。而後的AssetBundle.loadAsset直接通過IO從磁盤緩存中獲取。
AssetBundle.loadFromFile 與老版本CreatFromFile機制上的區別在於,之前版本只支持從解壓後的AB文件創建資源,新版本對於無壓縮或者LZ4方式的AB文件可以直接創建AssetBundle對象。
UWA關於AssetBundle的建議:
1/ 對於需要常駐內存的Bundle文件來說,優先考慮減小內存佔用,因此對於存放非Prefab資源(特別是紋理)的Bundle文件,可以考慮使用WWW.LoadFromCacheOrDownload或AssetBundle.CreateFromFile加載,從而避免WebStream常駐內存;
2/ 而對於存放較多Prefab資源的Bundle,則考慮使用new WWW加載,因爲這類Bundle用WWW.LoadFromCacheOrDownload加載時產生的SerializedFile可能會比new WWW產生的WebStream更大。
3/ 對於加載完後即卸載的Bundle文件,則分兩種情況:優先考慮速度(加載場景時)和優先考慮流暢度(遊戲進行時)。
1)加載場景的情況下,需要注意的是避免WWW對象的逐個加載導致的CPU空閒,可以考慮使用加載速度較快的WWW.LoadFromCacheOrDownload或AssetBundle.CreateFromFile,但需要避免後續大量地進行Load資源的操作,引起IO開銷(可以嘗試直接LoadAll)。
2) 遊戲進行的情況下,則需要避免使用同步操作引起卡頓,因此可以考慮使用new WWW配合AssetBundle.LoadAsync來進行平滑的資源加載,但需要注意的是,對於Shader、較大的Texture等資源,其初始化操作通常很耗時,容易引起卡頓,因此建議將這類資源在加載場景時進行預加載。
只在Bundle需要加密的情況下,考慮使用CreateFromMemory,因爲該接口加載速度較慢。
儘量避免在遊戲進行中調用Resources.UnloadUnusedAssets(),因爲該接口開銷較大,容易引起卡頓,可嘗試使用Resources.Unload(obj)來逐個進行卸載,以保證遊戲的流暢度。
AB加載卸載的操作流:
各種加載方式的內存、性能對比圖:
內存優化&流暢度(fps)優化
代碼GC和卡頓:
字符串拼接、
循環內部New對象、
反射減損、FieldInfo/MethodInfo緩存
循環for/foreach/iterator、foreach效率最差
裝箱拆箱,
緩存所需的動態MonoBehaviour組件,或者在頻繁instantiate/destroy應考慮pooling
異步waitfor進行緩存
不再運行時大量使用閉包(閉包效率?)
儘可能重用容器,以及容器操作的合理性(dic/list擴容,移除順序)
不要大量使用delegate的-=/+=,
當你的對象訂閱了外部的事件,而又沒有取消訂閱,那麼該對象是不會被GC回收的!這會造成很恐怖的問題,產生了幾千萬個對象沒法被回收。而且匿名函數無法取消訂閱,就算是兩個代碼格式完全一樣的匿名函數,編譯器生成的也是兩個不同的方法簽名。鏈接:http://www.cnblogs.com/buptzym/archive/2013/03/15/2962300.html
減少不必要的 shader varients
內存:
如果有較大的assetBundle,不要使用lzma格式,使用lz4
確保AssetBundle裏沒有重複的資源(AB依賴處理)
確保資源正確加載和卸載
不需要RW的texture&mesh關閉RW
不需要的texture關閉mipmap
模型頂點的normals和tangents,應該在導入設置或playersetting裏去除
確保大多數紋理使用壓縮格式(後處理工具相關)
確保貼圖尺寸合理、確保mesh面數合理
AnimationClip的分情況加載
fps:
減少meshColider的使用
適當情況下使用static batching/dynamic batching/自定義 batching
UI圖集的使用,動靜態分離,避免材質穿插、
使用合理的光照方案
使用合理的後處理
合理的骨骼數
合理的半透明物體佔屏比例,避免過多OverDraw
避免使用Unity自帶的地形系統
以下是關於品質控制
畫面質量控制:
**基本品質控制
實時陰影品質、骨骼動畫質量、紋理質量、垂直同步
**角色品質控制
根據和玩家主角的距離改變角色的渲染,如:是否開啓描邊、角色陰影模式實時/投影片兒/關閉、根據距離控制動畫更新頻率
**其他
分辨率整體縮放、根據對象layer控制渲染距離、根據配置切換抗鋸齒類型、後處理開關:FXAA(快速抗鋸齒/bloom/調色/鏡頭精神)
角色渲染優化:
**角色渲染合併
****紋理合並(通過相機拍攝RT合併、通過獲取TextureRawData合併、通過GraphicsCopy合併)
支持不同平臺下支持不同的紋理壓縮格式,shader實際上對不同類型圖的精度要求不同。
****Mesh合併
Unity的Mesh合併方法的問題:控制力不足、submesh合併會複製頂點,頂點數據翻倍
自定義mesh合併:獲取所有mesh頂點、法線等數據、重新拼接成一個mesh。
****重新綁定動畫:skinMeshrender設置正確的bones、mesh有正確的BindPose--骨骼對應頂點信息。
bindpose計算量巨大,使用ComputeShader將計算量推給GPU。
bindPose預先烘培mesh數據
部分不適合做合併的角色組件不參與合併。
總歸是在內存和DrawCall中尋找平衡。
場景畫面品質控制
****在較低配置上減少細節的渲染
****減少難以觀察到的細節渲染
****在不同的品質上真的做出性能差異
****在低端機上也能有更好的畫面
****在高端機上將性能集中到更有意義的地方
具體手段:植被分組,賦予不同優先級,場景特效根據重要性設置不同layer,決定特效細節的展示分級、氛圍特效控制,設置相機最遠渲染距離。
lua基礎 / lua + ugui / lua和c#交互
c#和lua交互是怎麼實現的?
從最早的lua純反射調用C# ---> 純C#實現的lua虛擬機 ---->luajit+c#靜態lua導出方案
猜想1:lua虛擬機有lua堆棧的完全控制權,lua調用C#需提供C#函數的橋接代碼,並將其註冊到lua虛擬機中,即壓入lua棧。
c#調lua,首先lua虛擬機從lua棧中獲取函數信息,然後在lua編譯器在Global Table查找luafunction,並運行返回結果,將結果壓入lua棧,宿主語言可以訪問lua棧中的內存數據,返回給c#。
所以最重要的是搞清楚lua虛擬機工作原理和lua堆棧訪問。
tips:如何在lua調用中體現c#語言中的高級特性,取決於lua框架(xlua、tolua)的實現?
xlua如何實現hotfixed?
在需要熱更的類或者方法上打上[hotfix]標籤,然後在lua調c#的橋接代碼中獲取熱更標識,如果出現標識則執行lua補丁代碼,否則執行c#原生代碼。