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。
<ignore_js_op>
在右側面板中可以找到VSync Count,把它選成Don't Sync。
<ignore_js_op>
這就關閉了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.自帶的合並必須勾選靜態。
<ignore_js_op>
所有被勾選了“Static”的GameObject,其中的Mesh Filter中的mesh都會被合並到 "Combined Mesha (root: scene)" 中
2.也可以用腳本來合並mesh 。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
using
UnityEngine;
using
System.Collections;
public
class
MyClass : MonoBehaviour
{
void
Start ()
{
MeshFilter [] meshFilters = GetComponentsInChildren<MeshFilter> ();
CombineInstance[] combine =
new
CombineInstance[meshFilters.Length];
for
(
int
i = 0; i < meshFilters.Length; i++) {
combine [i].mesh = meshFilters [i].sharedMesh;
combine [i].transform = meshFilters [i].transform.localToWorldMatrix;
meshFilters [i].gameObject.active =
false
;
}
transform.GetComponent<MeshFilter> ().mesh =
new
Mesh ();
transform.GetComponent<MeshFilter> ().mesh.CombineMeshes (combine);
transform.gameObject.active =
true
;
}
}
|
1. 先在 Unity 中建立 空物件 ( Empty )
2. 再創建2個 Cube 方塊,並放入 空物件底下 (可以改成你自己的模型)
3. 把 MyClass 代碼丟進 空物件上 。
4. (可選) 建立一個 Material 材質,並且丟進 空物件上
5. 執行
前
<ignore_js_op>
后
<ignore_js_op>
========================================分割線====================================
- 角色Material數量
2-3個
- 骨骼數量
小於30個
- 面片數量
300-1500
- 一般角色應該沒有IK結點
這是因為角色的動作大多數都是事先設定好的,並不需要經過IK操作來進行實時計算(Rogdoll除外),所以在模型導入時,不要將IK結點一起導入。
2、靜態實體
- 不要附加Animation Component
在靜態實體上附加Animation部件雖然對結果沒有影響,但卻會增加一定的CPU開銷來調用這一組件,所以盡量去掉該組件。
- 網格頂點數
小於500
- UV值范圍盡量不要超過(0, 1)區間
盡量保證UV值不越界,這對於將來的紋理拼合優化很有幫助。
3、地形
- 地形的分辨率大小
長寬均盡量小於257。這是因為地形太大,會造成大量頂點數據,給你的內存帶寬造成一定的影響,在目前的ios設備中,內存帶寬是非常有限的,需要盡量節省。同時,如果用Unity自帶的地形,一定也要使用Occlusion Culling,因為Unity的刷地形工具雖然方便,但卻是framekiller,刷過之后,你會發現drawcall增加的非常多。
- 混合紋理數量
不要超過4。地形的混合操作是很耗時的,應該盡量避免。能合並的紋理盡量合並。
4、紋理
- 紋理格式
建議png或tga。不用轉成ios硬件支持的PVRTC格式,因為Unity在發布時會幫你自動轉的。
- 紋理尺寸
長寬小於1024。同時應該盡可能地小,夠用就好,以保證紋理對內存帶寬的影響達到最小。
- 支持Mipmap
建議生成Mipmap。雖然這種做法會增加一些應用程序的大小,但在游戲運行時,系統會根據需求應用Mipmap來渲染,從而減少內存帶寬。
- 檢查Alpha值
如果紋理的alpha通道均為1,則用RGB的24位紋理來代替RGBA的32位紋理。(據說Unity內部會進行自動檢測)
5、光源
- 光源“Important”個數
建議1個,一般為方向光。“Important”個數應該越小越少。個數越多,drawcall越多。
- Pixel Light數目
1-2個。
6、粒子特效
- 屏幕上的最大粒子數
建議小於200個粒子。
- 每個粒子發射器發射的最大粒子數
建議不超過50個。
- 粒子大小
如果可以的話,粒子的size應該盡可能地小。因為Unity的粒子系統的shader無論是alpha test還是alpha blending都是一筆不小的開銷。同時,對於非常小的粒子,建議粒子紋理去掉alpha通道。
- 盡量不要開啟粒子的碰撞功能。
非常耗時。
7、音頻
- 游戲中播放時間較長的音樂(如背景音樂)
使用.ogg或.mp3的壓縮格式。
- 較短音樂(如槍聲)
使用.wav和.aif的未壓縮音頻格式。
8、相機
- 裁剪平面
將遠平面設置成合適的距離。遠平面過大會將一些不必要的物體加入渲染,降低效率。
- 根據不同的物體設置不同的遠裁剪平面
Unity提供了可以根據不同的layer來設置不同的view distance,所以我們可以實現將物體進行分層,大物體層設置的可視距離大些,而小物體層可以設置地小些,另外,一些開銷比較大的實體(如粒子系統)可以設置得更小些等等。
9、碰撞
- 盡量不用MeshCollider
如果可以的話,盡量不用MeshCollider,以節省不必要的開銷。如果不能避免的話,盡量用減少Mesh的面片數,或用較少面片的代理體來代替。
10、其他
- Drawcall
盡可能地減少Drawcall的數量。IOS設備上建議不超過100。減少的方法主要有如下幾種:Frustum Culling,Occlusion Culling,Texture Packing。Frustum Culling是Unity內建的,我們需要做的就是尋求一個合適的遠裁剪平面;Occlusion Culling,遮擋剔除,Unity內嵌了Umbra,一個非常好OC庫。但Occlusion Culling也並不是放之四海而皆准的,有時候進行OC反而比不進行還要慢,建議在OC之前先確定自己的場景是否適合利用OC來優化;Texture Packing,或者叫Texture Atlasing,是將同種shader的紋理進行拼合,根據Unity的static batching的特性來減少draw call。建議使用,但也有弊端,那就是一定要將場景中距離相近的實體紋理進行拼合,否則,拼合后很可能會增加每幀渲染所需的紋理大小,加大內存帶寬的負擔。這也就是為什么會出現“DrawCall降了,渲染速度也變慢了”的原因。
- 非運動物體盡量打上Static標簽
Unity在運行時會對static物體進行自動優化處理,所以應該盡可能將非運行實體勾上static標簽。
- 場景中盡可能地使用prefab
盡可能地使用prefab的實例化物體,以降低內存帶寬的負擔。檢查實體的PrefabType,盡量將其變成PrefabInstance,而不是ModelPrefabInstance。
========================================分割線====================================
移動平台相對於PC機,具有體積小,計算弱,帶寬少的特點。
因此做手機游戲的開發,優化的方向,與力度對比PC游戲都有所區別。
必須要做到優化流程,合理利用資源。
目前在手機上面,還不能夠像PC游戲那樣追求高質量渲染效果,為了讓手機不那么容易發燙,還要控制cpu,gpu,不能讓他們全速運算。
材質方面:
紋理方面,建議使用壓縮紋理,
Android上面使用ETC1,蘋果上面使用PVRTC。
UV坐標控制在0到1之間,人物模型面數控制在1500內,骨骼控制在30個以內。
場景中使用一個主光(不能再多了)。
盡量減少alphaTest和alphaBlend材質的使用。在手機上,這是很殺效率的。
骨骼動畫方面:
在動畫方面可以考慮不使用插值,固定的幀率的動畫。
如果要做插值,考慮使用四元數(表示旋轉)和向量(表示位移)來做插值。
四元數做插值速度比矩陣來的快,Slerp提供了平滑插值。
========================================分割線====================================
優化的常規技巧
剖析你的游戲。
不要花費時間來優化那些晦澀的代碼或者縮減圖形文件的大小,除非這是你游戲的瓶頸。
第一次剖析你的游戲將會使你發現你游戲的瓶頸。Apple's Shark是一個很好的用來剖析基於OpenGL的程序的工具。
再次剖析你的游戲。
優化之后不要忘記再剖析一次你的游戲,這樣可以檢查你所做的優化是否達到了預期的效果。
當然,這樣做也可能會使你發現更多的瓶頸。
流程第一、性能第二。花費時間來使你游戲的創建盡可能地流暢。
盡可能快地修正游戲中的錯誤將會使你后期更容易優化你的游戲。
在Scene View中測試場景。
這樣做將會使你清楚了解這個場景中的物體或者附加在物體上的腳本是否降低了游戲性能。
如果Scene View反應遲鈍,那么有可能是圖形方面的原因,如果Scene View反應不遲鈍,那么瓶頸可能出在腳本或者物理系統上。
禁用指定游戲物體。
在play模式下,嘗試禁用並啟用游戲物體來排查出游戲慢的原因。
網格
如果可能的話,把相鄰的物體(網格)合並為一個只有一個材質的物體(網格)。比如,你的游戲中包含一個桌子,上面有一堆東西,你完全可以在3D程序中將它們合並在一起(這可能也需要你將這些物體的紋理合並為一個大的紋理集)。減少需要渲染的物體的數量可以極大地提高游戲性能。
不要有不必要的網格。
如果你的游戲場景中有一個人物,那么他應該是一個網格。如果你有一個船,那么它也應該只是一個網格。
每一個網格只用一種材質。
使用極少的面數的網格(比如500個多邊形以下)。
最好把你人物的三角面數量控制在1500-2000個之間。
這個數量可以說是游戲質量和性能之間一個均衡值。如果你的模型有四邊形,那么在導入模型的時候,引擎將會把每個四邊形變為兩個三角形。
光照
像素光。
像素光可以讓你的游戲看起來效果很牛逼,但是不要使用過多的像素光。
在你的游戲中可以使用質量管理器來調節像素光的數量來取得一個性能和質量的均衡點.
性能占用順序:聚光燈>點光源>平行光。
一個好的點亮場景的方法就是先得到你想要的效果,然后看看哪些光更重要;
在保持光效的前提下看看哪些光可以去掉。
點光源和聚光燈只影響它們范圍內的網格。
如果一個網格處於點光源或者聚光燈的照射范圍之外,並且光源的attenuate開關是打開的,那么這個網格將不會被光源所影響,這樣就可以節省性能開銷。
這樣做理論上來講可以使用很多小的點光源而且依然能有一個好的性能,因為這些光源只影響一小部分物體。
一個網格在有8個以上光源影響的時候,只響應前8個最亮的光源。
貼圖
在外觀不變的前提下,貼圖大小越小越好。
如果你的顯卡的顯存不夠大的話,你游戲中的貼圖將會被轉存到系統內存中,在顯卡調用它們的時候再傳到顯卡中。
對於比較新的電腦來說,內存和顯卡之間有足夠的帶寬來達到一個很好的性能;
如果你很無恥地用了巨多的大圖片的話,在低顯存的電腦上運行你的游戲的時候,你的游戲必然會掛掉。
倒是沒有必要在圖形編輯軟件中調整貼圖的大小。你可以在unity導入貼圖的時候進行調整。
不要使用低質量的圖片。
在小播放界面的游戲中使用低質量的jpeg圖片或者低色彩的png圖片亦或是gif圖片沒什么問題。
在發布游戲的時候,引擎會自動壓縮這些圖片,多重壓縮和解壓將會降低圖片的質量,所以最好保持貼圖文件的分辨率為原始分辨率。
這樣就會減少多重壓縮和解壓所導致的圖片失真現象。
Shaders
多重效果的shader就比看起來樣式很單一的shader要更耗費資源。
同樣在一個擁有貼圖和光反射的物體上,使用VertexLit Diffuse shader無疑是最省資源的。
========================================分割線====================================
在美術制作場景的過程中,會使用到大量的粒子系統。
比如場景中的火把。在我們的一個地下城場景中,美術們放置了大量的火把。整個場景中的各個地方,有100來個火把。
unity中,在攝像機范圍外的粒子系統雖然不會被繪制。
但是update是一直持續的。這也就意味着,這100多個火把,不論是否可見都在更新。
這個設計應該是很不合理的,在我看過的其他引擎中,都會有一個開關,來控制不可見的粒子系統是否需要update。
有的粒子系統在不可見的時候需要更新,比如爆炸。有的不需要更新,比如火堆火把。
為了避免不必要的update開銷,尤其是最后游戲是要發布到頁游平台(web player只能使用一個cpu的核)。
於是寫了一個腳本,控制不可見的粒子系統就不更新。
該腳本主要是用到了2個MonoBehaviour的函數。
OnBecameInvisible() 當變為不可見 和 OnBecameVisible() 當變成可見。
要這2個函數起作用的前提是,該GameObject綁定了MeshRender組件。
所以,我們要在粒子系統的GameObject放置在一個GameObject 下,且給該GameObject綁定一個MeshRender 與 MeshFilter。
MeshFilter中的mesh可以隨便找個cube。
在Start() 的時候,把最GameObject的scale設置為很小,以保證該cube不被看見。
其實遍歷所有的child,把active設置為false。
在OnBecameVisible 中 遍歷所有child,把active設置為true。
在OnBecameInvisible中 遍歷所有child,把active設置為false。
轉自:http://www.unitymanual.com/thread-24302-1-1.html
流暢的游戲玩法來自流暢的幀率,而我們即將推出的動作平台游戲《Shadow Blade》已經將在標准iPhone和iPad設備上實現每秒60幀視為一個重要目標。
以下是我們在緊湊的優化過程中提升游戲運行性能,並實現目標幀率時需要考慮的事項。
當基本游戲功能到位時,就要確保游戲運行表現能夠達標。我們衡量游戲運行表現的一個基本工具是Unity內置分析器以及Xcode分析工具。使用Unity分析器來分析設備上的運行代碼真是一項寶貴的功能。
我們總結了這種為將目標設備的幀率控制在60fps而進行衡量、調整、再衡量過程的中相關經驗。
一、遇到麻煩時要調用“垃圾回收器”(Garbage Collector,無用單元收集程序,以下簡稱GC)
由於具有C/C++游戲編程背景,我們並不習慣無用單元收集程序的特定行為。確保自動清理你不用的內存,這種做法在剛開始時很好,但很快你就公發現自己的分析器經常顯示CPU負荷過大,原因是垃圾回收器正在收集垃圾內存。這對移動設備來說尤其是個大問題。要跟進內存分配,並盡量避免它們成為優先數,以下是我們應該采取的主要操作:
1.移除代碼中的任何字符串連接,因為這會給GC留下大量垃圾。
2.用簡單的“for”循環代替“foreach”循環。由於某些原因,每個“foreach”循環的每次迭代會生成24字節的垃圾內存。一個簡單的循環迭代10次就可以留下240字節的垃圾內存。
3.更改我們檢查游戲對象標簽的方法。用“if (go.CompareTag (“Enemy”)”來代替“if (go.tag == “Enemy”)” 。在一個內部循環調用對象分配的標簽屬性以及拷貝額外內存,這是一個非常糟糕的做法。
4.對象庫很棒,我們為所有動態游戲對象制作和使用庫,這樣在游戲運行時間內不會動態分配任何東西,不需要的時候所有東西反向循環到庫中。
5.不使用LINQ命令,因為它們一般會分配中間緩器,而這很容易生成垃圾內存。
二、謹慎處理高級腳本和本地引擎C++代碼之間的通信開銷。
所有使用Unity3D編寫的游戲玩法代碼都是腳本代碼,在我們的項目中是使用Mono執行時間處理的C#代碼。任何與引擎數據的通信需求都要有一個進入高級腳本語言的本地引擎代碼的調用。這當然會產生它自己的開銷,而盡量減少游戲代碼中的這些調用則要排在第二位。
1.在這一情景中四處移動對象要求來自腳本代碼的調用進入引擎代碼,這樣我們就會在游戲玩法代碼的一個幀中緩存某一對象的轉換需求,並一次僅向引擎發送一個請求,以便減少調用開銷。這種模式也適用於其他相似的地方,而不僅局限於移動和旋轉對象。
2.將引用本地緩存到元件中會減少每次在一個游戲對象中使用 “GetComponent” 獲取一個元件引用的需求,這是調用本地引擎代碼的另一個例子。
三、物理效果
1.將物理模擬時間步設置到最小化狀態。在我們的項目中就不可以將讓它低於16毫秒。
2.減少角色控制器移動命令的調用。移動角色控制器會同步發生,每次調用都會耗損極大的性能。我們的做法是緩存每幀的移動請求,並且僅運用一次。
3.修改代碼以免依賴“ControllerColliderHit” 回調函數。這證明這些回調函數處理得並不十分迅速。
4.面對性能更弱的設備,要用skinned mesh代替physics cloth。cloth參數在運行表現中發揮重要作用,如果你肯花些時間找到美學與運行表現之間的平衡點,就可以獲得理想的結果。
5.在物理模擬過程中不要使用ragdolls,只有在必要時才讓它生效。
6.要謹慎評估觸發器的“onInside”回調函數,在我們的項目中,我們盡量在不依賴它們的情況下模擬邏輯。
7.使用層次而不是標簽。我們可以輕松為對象分配層次和標簽,並查詢特定對象,但是涉及碰撞邏輯時,層次至少在運行表現上會更有明顯優勢。更快的物理計算和更少的無用分配內存是使用層次的基本原因。
8.千萬不要使用Mesh對撞機。
9.最小化碰撞檢測請求(例如ray casts和sphere checks),盡量從每次檢查中獲得更多信息。
四、讓AI代碼更迅速
我們使用AI敵人來阻攔忍者英雄,並同其過招。以下是與AI性能問題有關的一些建議:
1.AI邏輯(例如能見度檢查等)會生成大量物理查詢。可以讓AI更新循環設置低於圖像更新循環,以減少CPU負荷。
五、最佳性能表現根本就不是來自代碼!
沒有發生什么情況的時候,就說明性能良好。這是我們關閉一切不必要之物的基本原則。我們的項目是一個側邊橫向卷軸動作游戲,所以如果不具有可視性時,就可以關閉許多動態關卡物體。
1.使用細節層次的定制關卡將遠處的敵人AI關閉。
2.移動平台和障礙,當它們遠去時其物理碰撞機也會關閉。
3.Unity內置的“動畫挑選”系統可以用來關閉未被渲染對象的動畫。
4.所有關卡內的粒子系統也可以使用同樣的禁用機制。
六、回調函數!那么空白的回調函數呢?
要盡量減少Unity回調函數。即使敵人回調函數存在性能損失。沒有必要將空白的回調函數留在代碼庫中(有時候介於大量代碼重寫和重構之間)。
七、讓美術人員來救場
在程序員抓耳撓腮,絞盡腦汁去想該如何讓每秒運行更多幀時,美術人員總能神奇地派上大用場。
1.共享游戲對象材料,令其在Unity中處於靜止狀態,可以讓它們綁定在一起,由此產生的簡化繪圖調用是呈現良好移動運行性能的重要元素。
2.紋理地圖集對UI元素來說尤其有用。
3.方形紋理以及兩者功率的合理壓縮是必不可少的步驟。
4.我們的美術人員移除了所有遠處背景的網格,並將其轉化為簡單的2D位面。
5.光照圖非常有價值。
6.我們的美術人員在一些關口移除了額外頂點。
7.使用合理的紋理mip標准是一個好主意(游戲邦注:要讓不同分辨率的設備呈現良好的幀率時尤其如此)。
8.結合網格是美術人員可以發揮作用的另一個操作。
9.我們的動畫師盡力讓不同角色共享動畫。
10.要找到美學/性能之間的平衡,就免不了許多粒子效果的迭代。減少發射器數量並盡量減少透明度需求也是一大挑戰。
八、要減少內存使用
使用大內存當然會對性能產生負面影響,但在我們的項目中,我們的iPod由於超過內存上限而遭遇了多次崩潰事件。我們的游戲中最耗內存的是紋理。
1.不同設備要使用不同的紋理大小,尤其是UI和大型背景中的紋理。《Shadow Blade》使用的是通用型模板,但如果在啟動時檢測到設備大小和分辨率,就會載入不同資產。
2.我們要確保未使用的資產不會載入內存。我們必須遲一點在項目中找到僅被一個預制件實例引用,並且從未完全載入內存中實例化的資產。
3.去除網格中的額外多邊形也能實現這一點。
4.我們應該重建一些資產的生周期管理。例如,調整主菜單資產的加載/卸載時間,或者關卡資產、游戲音樂的有效期限。
5.每個關卡都要有根據其動態對象需求而量身定制的特定對象庫,並根據最小內存需求來優化。對象庫可以靈活一點,在開發過程中包含大量對象,但知道游戲對象需求后就要具體一點。
6.保持聲音文件在內存的壓縮狀態也是必要之舉。
加強游戲運行性能是一個漫長而具有挑戰性的過程,游戲開發社區所分享的大量知識,以及Unity提供的出色分析工具為《Shadow Blade》實現目標運行性能提供了極大幫助。
轉自http://gamerboom.com/archives/76214
1、在使用數組或ArrayList對象時應當注意
- length=myArray.Length;
- for(int i=0;i<length;i++)
- {
- }
避免
- for(int i=0;i<myArray.Length;i++)
- {
- }
2、如果沒有必要每幀都處理,則可以每隔幾幀處理一次
- void Update(){ if(Time.frameCount%6==0) { DoSomething(); }}
3、定時重復調用可以使用InvokeRepeating函數實現,比如,啟動0.5秒后每隔1秒執行一次 DoSomeThing 函數:
- void Start()
- {
- InvokeRepeating("DoSomeThing", 0.5f, 1.0f);
- }
4、少使用臨時變量,特別是在Update OnGUI等實時調用的函數中。
- void Update()
- {
- Vector3 pos;
- pos=transform.position;
- }
可以改為:
- private Vector3 pos;
- void Update()
- {
- pos=transform.position;
- }
5、主動進行垃圾回收
- void Update()
- {
- if(Time.frameCount%50==0)
- {
- System.GC.Collection();
- }
- }
6、優化數學運算,盡量避免使用float,而使用int,特別是在手機游戲中,盡量少用復雜的數學函數,比如sin,cos等函數。改除法/為乘法,例如:使用x*0.5f而不是 x/2.0f 。
7、壓縮 Mesh
導入 3D 模型之后,在不影響顯示效果的前提下,最好打開 Mesh Compression。 Off, Low, Medium, High 這幾個選項,可酌情選取。對於單個Mesh最好使用一個材質。
8、 運行時盡量減少 Tris 和 Draw Calls
預覽的時候,可點開 Stats,查看圖形渲染的開銷情況。特別注意 Tris 和 Draw Calls 這兩個參數。 一般來說,要做到: Tris 保持在 7.5k 以下 ,Draw Calls 保持在 35 以下。
9、避免大量使用 Unity 自帶的 Sphere 等內建 Mesh
Unity 內建的 Mesh,多邊形的數量比較大,如果物體不要求特別圓滑,可導入其他的簡單3D模型代替。
10、如果可能,將GameObject上不必要的腳本disable掉。如果你有一個大的場景在你的游戲中,並且敵方的位置在數千米意外,這是你可以disable你的敵方AI腳本直到它們接近攝像機為止。一個好的途徑來開啟或關閉GameObject是使用SetActiveRecursively(false),並且球形或盒型碰撞器設為trigger。
11、刪除空的Update方法。當通過Assets目錄創建新的腳本時,腳本里會包括一個Update方法,當你不使用時刪除它。
12、引用一個游戲對象的最合乎邏輯的組件。有人可能會這樣寫someGameObject.transform,gameObject.rigidbody.transform.gameObject.rigidbody.transform,但是這樣做了一些不必要的工作,你可以在最開始的地方引用它,像這樣:
privateTransform myTrans;
void Start()
{
myTrans=transform;
}
13、協同是一個好方法。可以使用協同程序來代替不必每幀都執行的方法。(還有InvokeRepeating方法也是一個好的取代Update的方法)。
14、盡可能不要再Update或FixedUpdate中使用搜索方法(例如GameObject.Find()),你可以像前面那樣在Start方法里獲得它。
15、不要使用SendMessage之類的方法,他比直接調用方法慢了100倍,你可以直接調用或通過C#的委托來實現。
16、使用javascript或Boo語言時,你最好確定變量的類型,不要使用動態類型,這樣會降低效率,你可以在腳本開頭使用#pragmastrict 來檢查,這樣當你編譯你的游戲時就不會出現莫名其妙的錯誤了。
轉自:http://blog.csdn.net/yesy10/article/details/7847926