1、美術(shù)篇
·美術(shù)規(guī)范:主要包括材質(zhì)數(shù)量、模型三角面、紋理尺寸、粒子數(shù)量、動(dòng)畫(huà)幀頻。
a、對(duì)于導(dǎo)入unity的模型
?需要注意:若勾選上圖中”Read/Write Enabled”將會(huì)使該模型在內(nèi)存中存在一份拷貝,用于在腳本中對(duì)模型進(jìn)行修改。若該模型不會(huì)在腳本中進(jìn)行修改,則不勾選。Optimize Mesh 必須勾選,便于引擎底層對(duì)Mesh進(jìn)行優(yōu)化處理。Normals & Tangents 中的Normals選項(xiàng)若設(shè)置為非Import項(xiàng),可以降低Memory,并減少ipa/apk包體容量。
b、對(duì)于unity貼圖
Unity支持目前主流的各種圖片格式,包括PSD,TGA,PNG,GIF,BMP,JPG,TIFF,PICT等。若圖片尺寸不是2的指數(shù),其所占用內(nèi)存的大小略大于原始尺寸,并且GPU對(duì)其進(jìn)行讀取的速度也有可能會(huì)略微偏慢。若勾選Generate Mip Maps,改貼圖所占用內(nèi)存會(huì)變大33%,但對(duì)整體性能有很大提升。
c、對(duì)于光照
移動(dòng)平臺(tái)推薦使用Baked或 Mixed,避免使用RealTime模式的光照。Render Mode 不推薦使用Important。使用Baked模式時(shí),在菜單Window->Lighting的Object標(biāo)簽頁(yè),可通過(guò)設(shè)置Scale In Lightmap的值,以變更lightmap中有多少像素值用于該GameObject的光照計(jì)算。
d、對(duì)于音效
Unity支持主流的各種音樂(lè)格式,包括mp3,ogg,wav,aif等。Load Type 中的Decompress On Load 選項(xiàng)不推薦用于大文件。大文件推薦使用 Compressed In Memory選項(xiàng)。Load In Background 如果勾選表示該音頻文件將在后臺(tái)加載,而不會(huì)造成主線程阻塞。
2、程序篇
a、邏輯架構(gòu)
設(shè)計(jì)時(shí)應(yīng)該遵循各功能模塊的獨(dú)立性和封裝性,并滿足即插即用。比如,整個(gè)游戲邏輯可分為;場(chǎng)景模塊,角色模塊,UI模塊,網(wǎng)絡(luò)通信模塊,戰(zhàn)斗模塊等。模塊化設(shè)計(jì)不僅游戲邏輯樹(shù)簡(jiǎn)單易懂,便于代碼審查,而且也有益于項(xiàng)目后期做性能優(yōu)化以及Bug檢查。比如,調(diào)試Bug時(shí),如果禁用某一個(gè)模塊,游戲正常運(yùn)行,并且Bug不再出現(xiàn),則Bug由該模塊引擎的概率很高。同理,在做優(yōu)化處理是,如果禁用某一個(gè)模塊,發(fā)現(xiàn)CPU負(fù)載下降很多,則該模塊造成性能瓶頸的概率也很高。
b、腳本應(yīng)用
Unity的腳本使用托管機(jī)制,如果某腳本需要掛載到場(chǎng)景GameObject上,則該腳本需要繼承于MonoBehaviour。在菜單Edit-> Project Settings -> Script Execution下,可更改各類(lèi)腳本的執(zhí)行順序。同時(shí),MonoBehaviour的執(zhí)行并非使用系統(tǒng)反射機(jī)制,而是基于隊(duì)列存儲(chǔ)形式。
為了減少代碼托管開(kāi)銷(xiāo),在設(shè)計(jì)具體腳本時(shí)可以做一些優(yōu)化處理。比如,有一個(gè)類(lèi)ClassA,繼承于MonoBehaviour,在其Update函數(shù)里會(huì)執(zhí)行具體邏輯。若該類(lèi)有30個(gè)實(shí)例同時(shí)存在,則會(huì)存在30次托管開(kāi)銷(xiāo),遇到此類(lèi)情況,建議刪除ClassA中的Update函數(shù),轉(zhuǎn)而由自定義的UpdateEx函數(shù)替代。同時(shí),額外編寫(xiě)一個(gè)ClassAManager類(lèi),其緩存一個(gè)ClassA的數(shù)組或者隊(duì)列,每次Update時(shí)遍歷該隊(duì)列,執(zhí)行每個(gè)實(shí)例的UpdateEx函數(shù)。(這個(gè)還真沒(méi)注意,以后要試試)
c、Asset管理
Unity中的Asset序列化支持二進(jìn)制、文本模式、混合模式三種,具體可以在菜單Editor Settings –> Asset Serialization 下進(jìn)行設(shè)置,文本模式采用YAML格式,增加可讀性。其中每一個(gè)資源文件都可以生成一個(gè)對(duì)應(yīng)的meta文件。(其實(shí)至今不知道這個(gè)序列化到底有什么好處,有哪位讀者大大知道,指點(diǎn)一下小菜鳥(niǎo)吧?。。。?/p>
在制作場(chǎng)景時(shí),建議把場(chǎng)景中的具體GameObject制作成Prefab,而不是直接使用FBX格式,這樣便于引擎底層做資源管理。
Unity引擎中各種美術(shù)資源都可以編譯成AssetBundle,包括紋理,模型,Prefab,AnimationClip,AudioClip等。同時(shí),AssetBundle支持壓縮與非壓縮格式,開(kāi)發(fā)者可根據(jù)項(xiàng)目實(shí)際情況進(jìn)行設(shè)置。
d、動(dòng)態(tài)更新
通常動(dòng)態(tài)更新包括美術(shù)資源與腳本的更新,美術(shù)資源建議使用AssetBundle,腳本更新在Android平臺(tái)上可使用dll反射實(shí)現(xiàn)(僅限Anadroid平臺(tái)),或者通過(guò)其它第三方非官方模式。(這部分目前還沒(méi)接觸到,自己做的東西還沒(méi)用過(guò)這個(gè),所以還在學(xué)習(xí)。。。。)
3、優(yōu)化篇
a、圖形優(yōu)化 - Graphics
要實(shí)現(xiàn)圖形優(yōu)化,首先需要熟悉圖形學(xué)整個(gè)渲染管線流程,在此對(duì)其作簡(jiǎn)要介紹:
應(yīng)用程序 (Application) -> 幾何體 (Geometry) -> 光柵化 (Rasterizer)。
其中,幾何體階段具體包括:模型變換(Model & View Transform) -> 頂點(diǎn)著色(Vertex Shading) -> 投影變換(Projection) -> 裁切(Clipping) -> 屏幕映射(Screen Mapping)。
光柵化階段包括: 三角設(shè)置(Triangle Setup) -> 三角遍歷(Triangle Traversal) -> 像素作色(Pixel Shading) - > 合并(Merging)。
進(jìn)行圖形優(yōu)化時(shí),首要步驟即為定位瓶頸在何處,CPU還是GPU?
如果渲染瓶頸發(fā)生在CPU,通常對(duì)CPU進(jìn)行的圖形相關(guān)優(yōu)化主要涉及以下幾點(diǎn):
合并模型(美術(shù)人員手動(dòng)合并或者使用引擎的Batching技術(shù))
在合并模型時(shí),如果被合并的模型并未使用同一材質(zhì),那么該合并操作并不會(huì)提升性能。同理,如果被合并的模型使用了多重材質(zhì),而并不共用貼圖,合并操作也不會(huì)提升性能。
減少材質(zhì)的使用數(shù)量,盡量材質(zhì)共用
紋理拼接,把多張小尺寸紋理拼接到同一張大尺寸紋理中
避免使用多重渲染,比如反射,陰影,像素光照等
動(dòng)畫(huà)優(yōu)化,包括減少骨骼數(shù)量,降低動(dòng)畫(huà)幀率等
CPU在圖形渲染中所承載的計(jì)算量沒(méi)有GPU那么高(前提是設(shè)備同時(shí)具備GPU和CPU),所以在進(jìn)行圖形優(yōu)化時(shí),更多是針對(duì)GPU端,其具體包括:
模型對(duì)象
調(diào)整模型三角面是優(yōu)化美術(shù)資源的基本步驟,如果一個(gè)角色模型1500面能達(dá)到要求,那為何要使用1600面呢。
當(dāng)場(chǎng)景中某些對(duì)象被標(biāo)記為Static時(shí),禁止在腳本中對(duì)其進(jìn)行位置,朝向,縮放更改,也就是如果需要更改一個(gè)對(duì)象的Transform屬性值,則改對(duì)象不應(yīng)該被標(biāo)記為Static。
在設(shè)計(jì)模型時(shí),盡量減少UV映射縫隙和硬邊的數(shù)量。
光照設(shè)計(jì)
在移動(dòng)設(shè)備上,盡量使用light map代替實(shí)時(shí)光照,即便美術(shù)人員需要很炫的光照效果,也可以預(yù)先由美術(shù)人員調(diào)節(jié)好實(shí)時(shí)光照效果后再進(jìn)行l(wèi)ight map烘焙。
在某些特定情況下,美術(shù)人員可能需要一些特定對(duì)象呈現(xiàn)出酷炫的效果,建議使用Shader實(shí)現(xiàn),而非采用增加額外的光源。
減少像素光的數(shù)量(像素光是指的什么?求指點(diǎn)),不僅可以降低CPU負(fù)載,也可以減少GPU消耗。如果場(chǎng)景中某像素光照作用的兩個(gè)模型對(duì)象距離相隔較遠(yuǎn),建議不要對(duì)該模型對(duì)象進(jìn)行合并操作。
Shader性能
Unity引擎為開(kāi)發(fā)者提供了大量的內(nèi)置Shader,基本滿足開(kāi)發(fā)者的項(xiàng)目需求。如果某些特殊效果需要自定義Shader,在編寫(xiě)Shader程序時(shí),需要注意一些具體細(xì)節(jié)。
在Shader程序中減少使用或者不使用條件語(yǔ)句。GPU在硬件層面上與CPU有著極大差異,GPU以ALU(邏輯運(yùn)算單元)著稱(chēng),而CPU則存在著大量的控制器。
定義變量時(shí),應(yīng)考慮變量需要的精度位寬(Float 為32位,half為16位,fixed為10位),比如定義的變量用于UV坐標(biāo),則類(lèi)型通常選擇half即可,如果選擇float,則會(huì)造成帶寬浪費(fèi)以及計(jì)算消耗增加。
避免使用復(fù)雜的數(shù)學(xué)計(jì)算函數(shù),比如sin,tan,pow,exp,log等,如果實(shí)在需要,建議單個(gè)Shader程序里該類(lèi)復(fù)雜函數(shù)的使用次數(shù)不超過(guò)一次。
移動(dòng)平臺(tái)避免使用Alpha Test和Alpha Blend指令,如果不可避免,建議使用Alpha Blend,而非Alpha Test。
紋理壓縮
壓縮紋理不僅可以節(jié)省內(nèi)存,同時(shí)也節(jié)省運(yùn)算帶寬。同時(shí),建議3D模型貼圖都應(yīng)生成對(duì)應(yīng)的Mipmaps,如果選擇生成Mipmaps,則該紋理對(duì)應(yīng)的內(nèi)存大小相對(duì)原先會(huì)變大33%左右,但如果不選擇生成Mipmaps,則在整體性能上會(huì)有很大損失。
LOD使用
Unity中關(guān)于LOD的使用有LOD Group和Camera.layerCullDistances兩種方式。其中LOD Group主要用于大型模型對(duì)象,而Camera.layerCullDistances主要用于碎片化的模型對(duì)象。
b、物理優(yōu)化
Unity引擎中物理計(jì)算更新在FixedUpdate中完成,根據(jù)具體的游戲項(xiàng)目,如果游戲物理更新頻率不需要太高,可以在菜單Project Settings -> Time 下更改Fixed TimeStep的值。
使用物理碰撞體時(shí),在滿足設(shè)計(jì)要求前提下,建議使用Sphere Collider 或者 Box Collider代替Mesh Collider。Mesh Collider和wheel Collider其計(jì)算較為復(fù)雜,能避免使用則避免之。
被標(biāo)記為Static的碰撞體,禁止對(duì)其移動(dòng)位置。
如果對(duì)象不需要Rigidbody組件,一律刪除。
在腳本中如果通過(guò)Physics.RaycastAll類(lèi)似的接口獲取固定對(duì)象,緩存所得到的對(duì)象,禁止通過(guò)程序中每幀調(diào)用該類(lèi)接口去獲取一個(gè)固定的對(duì)象。
c、程序優(yōu)化
程序優(yōu)化的根本在于設(shè)計(jì),在于程序員在編寫(xiě)程序時(shí)是否有細(xì)心思考。盡管Unity引擎本身由C++編寫(xiě),但上層邏輯腳本基于Mono體系,內(nèi)存管理使用GC機(jī)制。
GC機(jī)制在內(nèi)存管理存在實(shí)時(shí)性欠缺,而Mono內(nèi)存基于內(nèi)存池,即Mono所申請(qǐng)內(nèi)存不會(huì)得到釋放(只有在內(nèi)存池中內(nèi)存不夠使用時(shí),Mono才會(huì)申請(qǐng)新的內(nèi)存),只會(huì)返回內(nèi)存池。
基于以上機(jī)制限制,應(yīng)禁止頻繁申請(qǐng)內(nèi)存,盡量使用對(duì)象池管理對(duì)象,比如在Update函數(shù)里每幀都new 一個(gè)數(shù)組或者隊(duì)列,這樣極有可能造成GC還未回收先前的內(nèi)存,內(nèi)存池中內(nèi)存不足,又重復(fù)申請(qǐng)新的內(nèi)存,最終Mono內(nèi)存池越來(lái)越大,這是很多開(kāi)發(fā)者都曾遇到的問(wèn)題。
在Unity引擎層面,可以通過(guò)使用IL2CPP技術(shù),使腳本運(yùn)行速度更快,同時(shí),也可以在Script Call Optimization中設(shè)置忽略異常處理。針對(duì)具體腳本中負(fù)載瓶頸的定位,建議多使用引擎的Profiler工具。
(ps:對(duì)于程序優(yōu)化這部分,基本不理解,還是基礎(chǔ)差。。。。哪位能解釋一下,或者提供些相關(guān)資料。謝謝)
d、文件優(yōu)化
如果要降低整體文件大小,首先得知道整個(gè)項(xiàng)目中每類(lèi)資源文件具體大小。在Unity完成相關(guān)編譯后,選擇Console -> Open Editor Log選項(xiàng),會(huì)得到如下圖所示的信息:
(ps,然而我在windows下打開(kāi)log文件并沒(méi)有所有資源的大小描述。。。。糾正一下,在buliding的時(shí)候勾選這幾個(gè)就可以看見(jiàn)了。)

其包括了具體各類(lèi)資源的總大小,開(kāi)發(fā)者可按照文件大小建立優(yōu)化順序。其中,具體在設(shè)計(jì)到腳本大小優(yōu)化時(shí),根據(jù)項(xiàng)目組具體情況,可以考慮選擇.Net 2.0 Subset,在iOS平臺(tái)也可使用Stripping方法。同時(shí),建議把Resources文件夾下不曾使用的資源刪除,需要使用的資源用AssetBundle代替。Resources文件夾下文件太多會(huì)嚴(yán)重影響程序的啟動(dòng)時(shí)間。
文章摘自Unity官方微信,如有侵權(quán)請(qǐng)聯(lián)系本人下架。