Unity 項(xiàng)目經(jīng)驗(yàn)之談

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)系本人下架。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 111. [動(dòng)畫(huà)系統(tǒng)]如何將其他類(lèi)型的動(dòng)畫(huà)轉(zhuǎn)換成關(guān)鍵幀動(dòng)畫(huà)? 動(dòng)畫(huà)->點(diǎn)緩存->關(guān)鍵幀 112. [動(dòng)畫(huà)]Unit...
    胤醚貔貅閱讀 13,560評(píng)論 3 88
  • 原文地址 http://www.fx114.net/qa-75-172454.aspx 使用Profiler工具...
    IongX閱讀 6,260評(píng)論 1 11
  • This article is a record of my journey to learn Game Deve...
    蔡子聰閱讀 4,129評(píng)論 0 9
  • 這個(gè)是我剛剛整理出的Unity面試題,為了幫助大家面試,同時(shí)幫助大家更好地復(fù)習(xí)Unity知識(shí)點(diǎn),如果大家發(fā)現(xiàn)有什么...
    編程小火雞閱讀 4,007評(píng)論 2 34
  • 夢(mèng)與想 安靜的課上,又到了S老師宣布自習(xí)的時(shí)間了。還沒(méi)一會(huì)兒,S老師緩緩的向坐在最后一排的T同學(xué)走去說(shuō)道“Is t...
    豆豆豆豆愛(ài)吃布丁閱讀 439評(píng)論 0 0

友情鏈接更多精彩內(nèi)容