日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

unity3d优化收集摘录

發布時間:2023/12/8 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 unity3d优化收集摘录 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  Unity3D 對于移動平臺的支持無可厚非,但是也有時候用Unity3D 開發出來的應用、游戲在移動終端上的運行有著明顯的效率問題,比如卡、畫質等各種問題。

  影響因素:

  • Drawcall 值過大,所需要的 GPU 的處理性能較高,從而導致CPU的計算時間過長,于是就卡了。
  • 點、面過多,GPU 根據不同面的效果展開計算,并且CPU計算的數據也多,所以效果出來了。
  •   優化方式:

  • 對于模型:Mesh 合并,有個不錯的插件(DrawCall Minimizer???--->??直接上Asset Store 下載即可,免費的,而且有文檔,很容易上手)。
  • 對于UI:?盡量避免使用Unity3D自帶的 GUI 換用 NGUI或者EZGUI,因為這兩個UI插件對于UI中的圖片處理是將UI圖片放置在一個 Atlas 中,一個 Atlas 對應一個Drawcall。
  • 對于燈光:可以使用 Unity3D 自帶的??Lightmapping?插件來烘焙場景中的燈光效果到物體材質上。
  • 對于場景:可以使用 Unity3D 自帶的 Occlusion?Culling 插件把靜止不動的場景元素烘焙出來。
  • 對于特效:盡量把材質紋理合并。  
  •   在屏幕上渲染物體,引擎需要發出一個繪制調用來訪問圖形API(iOS系統中為OpenGL ES)。每個繪制調用需要進行大量的工作來訪問圖形API,從而導致了CPU方面顯著的性能開銷。Unity在運行時可以將一些物體進行合并,從而用一個繪制調用來渲染他們。這一操作,我們稱之為“批處理”。一般來說,Unity批處理的物體越多,你就會得到越好的渲染性能。?   Unity中內建的批處理機制所達到的效果要明顯強于使用幾何建模工具(或使用Standard Assets包中的CombineChildren腳本)的批處理效果。這是因為,Unity引擎的批處理操作是在物體的可視裁剪操作之后進行的。Unity先對每個物體進行裁剪,然后再進行批處理,這樣可以使渲染的幾何總量在批處理前后保持不變。但是,使用幾何建模工具來拼合物體,會妨礙引擎對其進行有效的裁剪操作,從而導致引擎需要渲染更多的幾何面片。   材質。只有擁有相同材質的物體才可以進行批處理。因此,如果你想要得到良好的批處理效果,你需要在程序中盡可能地復用材質和物體。如果你的兩個材質僅僅是紋理不同,那么你可以通過紋理拼合操作來將這兩張紋理拼合成一張大的紋理。一旦紋理拼合在一起,你就可以使用這個單一材質來替代之前的兩個材質了。如果你需要通過腳本來訪問復用材質屬性,那么值得注意的是改變Renderer.material將會造成一份材質的拷貝。因此,你應該使用Renderer.sharedMaterial來保證材質的共享狀態。?   動態批處理。如果動態物體共用著相同的材質,那么Unity會自動對這些物體進行批處理。動態批處理操作是自動完成的,并不需要你進行額外的操作。
  • 批處理動態物體需要在每個頂點上進行一定的開銷,所以動態批處理僅支持小于900頂點的網格物體。?
  • 如果你的著色器使用頂點位置,法線和UV值三種屬性,那么你只能批處理300頂點以下的物體;如果你的著色器需要使用頂點位置,法線,UV0,UV1和切向量,那你只能批處理180頂點以下的物體。請注意:屬性數量的限制可能會在將來進行改變。
  • 不要使用縮放尺度(scale)。分別擁有縮放尺度(1,1,1)和(2,2,2)的兩個物體將不會進行批處理。
  • 統一縮放尺度的物體不會與非統一縮放尺度的物體進行批處理。使用縮放尺度(1,1,1)和 (1,2,1)的兩個物體將不會進行批處理,但是使用縮放尺度(1,2,1)和(1,3,1)的兩個物體將可以進行批處理。
  • 使用不同材質的實例化物體(instance)將會導致批處理失敗。
  • 擁有lightmap的物體含有額外(隱藏)的材質屬性,比如:lightmap的偏移和縮放系數等。所以,擁有lightmap的物體將不會進行批處理(除非他們指向lightmap的同一部分)。
  • 多通道的shader會妨礙批處理操作。比如,幾乎unity中所有的著色器在前向渲染中都支持多個光源,并為它們有效地開辟多個通道。
  • 預設體的實例會自動地使用相同的網格模型和材質。
  •   靜態批處理。相對而言,靜態批處理操作允許引擎對任意大小的幾何物體進行批處理操作來降低繪制調用。因此,靜態批處理比動態批處理更加有效,你應該盡量低使用它,因為它需要更少的CPU開銷。為了更好地使用靜態批處理,你需要明確指出哪些物體是靜止的,并且在游戲中永遠不會移動、旋轉和縮放。想完成這一步,你只需要在檢測器(Inspector)中將Static復選框打勾即可。使用靜態批處理操作需要額外的內存開銷來儲存合并后的幾何數據。在靜態批處理之前,如果一些物體共用了同樣的幾何數據,那么引擎會在編輯以及運行狀態對每個物體創建一個幾何數據的備份。這并不總是一個好的想法,因為有時候,你將不得不犧牲一點渲染性能來防止一些物體的靜態批處理,從而保持較少的內存開銷。比如,將濃密森里中樹設為Static,會導致嚴重的內存開銷。靜態批處理目前只支持Unity iOS Advanced。
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Unity(或者說基本所有圖形引擎)生成一幀畫面的處理過程大致可以這樣簡化描述:引擎首先經過簡單的可見性測試,確定攝像機可以看到的物體,然后把這些物體的頂點(包括本地位置、法線、UV等),索引(頂點如何組成三角形),變換(就是物體的位置、旋轉、縮放、以及攝像機位置等),相關光源,紋理,渲染方式(由材質/Shader決定)等數據準備好,然后通知圖形API——或者就簡單地看作是通知GPU——開始繪制,GPU基于這些數據,經過一系列運算,在屏幕上畫出成千上萬的三角形,最終構成一幅圖像。

    在Unity中,每次引擎準備數據并通知GPU的過程稱為一次Draw Call。這一過程是逐個物體進行的,對于每個物體,不只GPU的渲染,引擎重新設置材質/Shader也是一項非常耗時的操作。因此每幀的Draw Call次數是一項非常重要的性能指標,對于iOS來說應盡量控制在20次以內,這個值可以在編輯器的Statistic窗口看到。

    Unity內置了Draw Call Batching技術,從名字就可以看出,它的主要目標就是在一次Draw Call中批量處理多個物體。只要物體的變換和材質相同,GPU就可以按完全相同的方式進行處理,即可以把它們放在一個Draw Call中。Draw Call Batching技術的核心就是在可見性測試之后,檢查所有要繪制的物體的材質,把相同材質的分為一組(一個Batch),然后把它們組合成一個物體(統一變換),這樣就可以在一個Draw Call中處理多個物體了(實際上是組合后的一個物體)。

    但Draw Call Batching存在一個缺陷,就是它需要把一個Batch中的所有物體組合到一起,相當于創建了一個與這些物體加起來一樣大的物體,與此同時就需要分配相應大小的內存。這不僅會消耗更多內存,還需要消耗CPU時間。特別是對于移動的物體,每一幀都得重新進行組合,這就需要進行一些權衡,否則得不償失。但對于靜止不動的物體來說,只需要進行一次組合,之后就可以一直使用,效率要高得多。

    Unity提供了Dynamic Batching和Static Batching兩種方式。Dynamic Batching是完全自動進行的,不需要也無法進行任何干預,對于頂點數在300以內的可移動物體,只要使用相同的材質,就會組成Batch。Static Batching則需要把靜止的物體標記為Static,然后無論大小,都會組成Batch。如前文所說,Static Batching顯然比Dynamic Batching要高效得多,于是,Static Batching功能是收費的……

    要有效利用Draw Call Batching,首先是盡量減少場景中使用的材質數量,即盡量共享材質,對于僅紋理不同的材質可以把紋理組合到一張更大的紋理中(稱為Texture Atlasing)。然后是把不會移動的物體標記為Static。此外還可以通過CombineChildren腳本(Standard Assets/Scripts/Unity Scripts/CombineChildren)手動把物體組合在一起,但這個腳本會影響可見性測試,因為組合在一起的物體始終會被看作一個物體,從而會增加GPU要處理的幾何體數量,因此要小心使用。

    對于復雜的靜態場景,還可以考慮自行設計遮擋剔除算法,減少可見的物體數量同時也可以減少Draw Call。

    總之,理解Draw Call和Draw Call Batching原理,根據場景特點設計相應的方案來盡量減少Draw Call次數才是王道,其它方面亦然。

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    寫在前面


    這一篇是在Digital Tutors的一個系列教程的基礎上總結擴展而得的~Digital Tutors是一個非常棒的教程網站,包含了多媒體領域很多方面的資料,非常酷!除此之外,還參考了Unity Cookie中的一個教程。還有很多其他參考在下面的鏈接中。


    這篇文章旨在簡要地說明一下常見的各種優化策略。不過對每個基礎有非常深入地講解,需要的童鞋可以自行去相關資料。


    還有一些我認為非常好的參考文章:
    Performance Optimization for Mobile Devices

    4 Ways To Increase Performance of your Unity Game
    Unite 2013 Optimizing Unity Games for Mobile Platforms

    Unity optimization Tips



    影響性能的因素


    首先,我們得了解,影響游戲性能的因素哪些,才能對癥下藥。對于一個游戲來說,有兩種主要的計算資源:CPU和GPU。它們會互相合作,來讓我們的游戲可以在預期的幀率和分辨率下工作。CPU負責其中的幀率,GPU主要負責分辨率相關的一些東西。


    總結起來,主要的性能瓶頸在于:

    • CPU
      • 過多的Draw Calls
      • 復雜的腳本或者物理模擬

    • 頂點處理
      • 過多的頂點
      • 過多的逐頂點計算

    • 像素(Fragment)處理
      • 過多的fragment,overdraws
      • 過多的逐像素計算

    • 帶寬
      • 尺寸很大且未壓縮的紋理
      • 分辨率過高的framebuffer


    對于CPU來說,限制它的主要是游戲中的Draw Calls。那么什么是Draw Call呢?如果你學過OpenGL,那么你一定還記得在每次繪圖前,我們都需要先準備好頂點數據(位置、法線、顏色、紋理坐標等),然后調用一系列API把它們放到GPU可以訪問到的指定位置,最后,我們需要調用_glDraw*命令,來告訴GPU,“嘿,我把東西都準備好了,你個懶家伙趕緊出來干活(渲染)吧!”。而調用_glDraw*命令的時候,就是一次Draw Call。那么為什么Draw Call會成為性能瓶頸呢(而且是CPU的瓶頸)?上面說到過,我們想要繪制圖像時,就一定需要調用Draw Call。例如,一個場景里有水有樹,我們渲染水的時候使用的是一個material以及一個shader,但渲染樹的時候就需要一個完全不同的material和shader,那么就需要CPU重新準備頂點數據、重新設置shader,而這種工作實際是非常耗時的。如果場景中,每一個物體都使用不同的material、不同的紋理,那么就會產生太多Draw Call,影響幀率,游戲性能就會下降。當然,這里說得很簡單,更詳細的請自行谷歌。其他CPU的性能瓶頸還有物理、布料模擬、粒子模擬等,都是計算量很大的操作。


    而對于GPU來說,它負責整個渲染流水線。它會從處理CPU傳遞過來的模型數據開始,進行Vertex Shader、Fragment Shader等一系列工作,最后輸出屏幕上的每個像素。因此它的性能瓶頸可能和需要處理的頂點數目的、屏幕分辨率、顯存等因素有關。總體包含了頂點和像素兩方面的性能瓶頸。在像素處理中,最常見的性能瓶頸之一是overdraw。Overdraw指的是,我們可能對屏幕上的像素繪制了多次。


    了解了上面基本的內容后,下面涉及到的優化技術有:

    • 頂點優化
      • 優化幾何體
      • 使用LOD(Level of detail)技術
      • 使用遮擋剔除(Occlusion culling)技術

    • 像素優化
      • 控制繪制順序
      • 警惕透明物體
      • 減少實時光照

    • CPU優化
      • 減少Draw Calls

    • 帶寬優化
      • 減少紋理大小
      • 利用縮放

    首先是頂點優化的部分。

    頂點優化

    優化幾何體


    這一步主要是為了針對性能瓶頸中的”頂點處理“一項。這里的幾何體就是指組成場景中對象的網格結構。
    3D游戲制作都由模型制作開始。而在建模時,有一條我們需要記住:盡可能減少模型中三角形的數目,一些對于模型沒有影響、或是肉眼非常難察覺到區別的頂點都要盡可能去掉。例如在下面左圖中,正方體內部很多頂點都是不需要的,而把這個模型導入到Unity里就會是右面的情景: ?

    在Game視圖下,我們可以查看場景中的三角形數目和頂點數目:

    可以看到一個簡單的正方形就產生了這么多頂點,這是我們不希望看到的。
    同時,盡可能重用頂點。在很多三維建模軟件中,都有相應的優化選項,可以自動優化網格結構。最后優化后,一個正方體可能只剩下8個頂點: ?

    它對應的頂點數和三角形數目如下:


    等等!這里,你可能要問了,為什么頂點數是24,而不是8呢?美術朋友們經常會遇到這樣的問題,就是建模軟件里顯示的模型頂點數和Unity中的不一樣,通常Unity會多很多。誰才是對的呢?其實,它們是站在不同的角度上計算的,都有各自的道理,但我們真正應該關心的是Unity里的數目。
    我們這里簡單解釋一下。三維軟件里更多地是站在我們人類的角度理解頂點的,即我們看見的一個點就是一個。而Unity是站在GPU的角度上,去計算頂點數目的。而在GPU看來,看起來是一個的很有可能它要分開處理,從而就產生了額外的頂點。這種將頂點一分為多的原因,主要有兩個:一個是UV splits,一個是Smoothing splits。而它們的本質其實都是因為對于GPU來說,頂點的每一個屬性和頂點之間必須是一對一的關系。UV splits的產生,是因為建模時,一個頂點的UV坐標有多個。例如之前的立方體的例子,由于每個面都有共同的頂點,因此在不同面上,同一個頂點的UV坐標可能發生改變。這對于GPU來說,這是不可理解的,因此它必須把這個頂點拆分成兩個具有不同UV坐標的定頂點,它才甘心。而Smoothing splits的產生也是類似的,不同的時,這次一個頂點可能會對應多個法線信息或切線信息。這通常是因為我們要決定一個邊是一條Hard Edge還是Smooth Edge。Hard Edge通常是下面這樣的效果(注意中間的折痕部分): ?

    而如果觀察它的頂點法線,就會發現,折痕處每個頂點其實包含了兩個不同的法線。因此,對于GPU來說,它同樣無法理解這樣的事情,因此會把頂點一分為二。而相反,Smooth Edge則是下面的情況: ?

    對于GPU來說,它本質上只關心有多少個頂點。因此,盡可能減少頂點的數目其實才是我們真正對需要關心的事情。因此,最后一條優化建議就是:移除不必要的Hard Edge以及紋理銜接,即避免Smoothing splits和UV?splits

    使用LOD(Level of detail)技術


    LOD技術有點類似于Mipmap技術,不同的是,LOD是對模型建立了一個模型金字塔,根據攝像機距離對象的遠近,選擇使用不同精度的模型。它的好處是可以在適當的時候大量減少需要繪制的頂點數目。它的缺點同樣是需要占用更多的內存,而且如果沒有調整好距離的話,可能會造成模擬的突變。
    在Unity中,可以通過LOD Group來實現LOD技術:
    ?


    通過上面的LOD Group面板,我們可以選擇需要控制的模型以及距離設置。下面展示了油桶從一個完整網格到簡化網格,最后完全被剔除的例子:
    ????



    使用遮擋剔除(Occlusion culling)技術


    遮擋剔除是用來消除躲在其他物件后面看不到的物件,這代表資源不會浪費在計算那些看不到的頂點上,進而提升性能。關于遮擋剔除,Unity Taiwan有一個系列文章大家可以看看(需翻墻):
    Unity 4.3 關于Occlusion Culling : 基本篇

    Unity 4.3 關于Occlusion Culling : 最佳做法

    Unity 4.3 關于Occlusion Culling : 錯誤診斷


    具體的內容大家可以自行查找。

    現在我們來談像素優化。

    像素優化


    像素優化的重點在于減少overdraw。之前提過,overdraw指的就是一個像素被繪制了多次。關鍵在于控制繪制順序。
    Unity還提供了查看overdraw的視圖,在Scene視圖的Render Mode->Overdraw。當然這里的視圖只是提供了查看物體遮擋的層數關系,并不是真正的最終屏幕繪制的overdraw。也就是說,可以理解為它顯示的是如果沒有使用任何深度檢驗時的overdraw。這種視圖是通過把所有對象都渲染成一個透明的輪廓,通過查看透明顏色的累計程度,來判斷物體的遮擋。


    上圖圖,紅色越是濃重的地方表示overdraw越嚴重,而且這里涉及的都是透明物體,這意味著性能將會受到很大影響。

    控制繪制順序


    需要控制繪制順序,主要原因是為了最大限度的避免overdraws,也就是同一個位置的像素可以需要被繪制多變。在PC上,資源無限,為了得到最準確的渲染結果,繪制順序可能是從后往前繪制不透明物體,然后再繪制透明物體進行混合。但在移動平臺上,這種會造成大量overdraw的方式顯然是不適合的,我們應該盡量從前往后繪制。從前往后繪制之所以可以減少overdraw,都是因為深度檢驗的功勞。
    在Unity中,那些Shader中被設置為“Geometry” 隊列的對象總是從前往后繪制的,而其他固定隊列(如“Transparent”“Overla”等)的物體,則都是從后往前繪制的。這意味這,我們可以盡量把物體的隊列設置為“Geometry” 。
    而且,我們還可以充分利用Unity的隊列來控制繪制順序。例如,對于天空盒子來說,它幾乎覆蓋了所有的像素,而且我們知道它永遠會在所有物體的后面,因此它的隊列可以設置為“Geometry+1”。這樣,就可以保證不會因為它而造成overdraws。

    時刻警惕透明物體


    而對于透明對象,由于它本身的特性(可以看之前關于Alpha Test和Alpha Blending的一篇文章)決定如果要得到正確的渲染效果,就必須從后往前渲染(這里不討論使用深度的方法),而且拋棄了深度檢驗。這意味著,透明物體幾乎一定會造成overdraws。如果我們不注意這一點,在一些機器上可能會造成嚴重的性能下面。例如,對于GUI對象來說,它們大多被設置成了半透明,如果屏幕中GUI占據的比例太多,而主攝像機又沒有進行調整而是投影整個屏幕,那么GUI就會造成屏幕的大量overdraws。

    因此,如果場景中大面積的透明對象,或者有很多層覆蓋的多層透明對象(即便它們每個的面積可以都不大),或者是透明的粒子效果,在移動設備上也會造成大量的overdraws。這是應該盡量避免的。
    對于上述GUI的這種情況,我們可以盡量減少窗口中GUI所占的面積。如果實在無能為力,我們可以把GUI繪制和三維場景的繪制交給不同的攝像機,而其中負責三維場景的攝像機的視角范圍盡量不要和GUI重疊。對于其他情況,只能說,盡可能少用。當然這樣會對游戲的美觀度產生一定影響,因此我們可以在代碼中對機器的性能進行判斷,例如首先關閉所有的耗費性能的功能,如果發現這個機器表現非常良好,再嘗試開啟一些特效功能。

    減少實時光照


    實時光照對于移動平臺是個非常昂貴的操作。如果只有一個平行光還好,但如果場景中包含了太多光源并且使用了很多多Passes的shader,那么很有可能會造成性能下降。而且在有些機器上,還要面臨shader失效的風險。例如,一個場景里如果包含了三個逐像素的點光源,而且使用了逐像素的shader,那么很有可能將Draw Calls提高了三倍,同時也會增加overdraws。這是因為,對于逐像素的光源來說,被這些光源照亮的物體要被再渲染一次。更糟糕的是,無論是動態批處理還是動態批處理(其實文檔中只提到了對動態批處理的影響,但不知道為什么實驗結果對靜態批處理也沒有用),對于這種逐像素的pass都無法進行批處理,也就是說,它們會中斷批處理。
    例如,下面的場景中,四個物體都被標識成了“Static”,它們使用的shader都是自帶的Bumped Diffuse。而所有的點光源都被標識成了“Important”,即是逐像素光。可以看到,運行后的Draw Calls是23,而非3。這是因為,只有“Forward Base”的Pass時發生了靜態批處理(這里的動態批處理由于多Pass已經完全失效了),節省了一個Draw Calls,而后面的“Forward Add” Pass,每一次渲染都是一個單獨的Draw Call(而且可以看到Tris和Verts數目也增加了):



    這點正如文檔中說的:The draw calls for “additional per-pixel lights” will not be batched。原因我不是很清楚,這里有一個討論,但里面的意思說是對靜態批處理沒有影響,和我這里的結果不一樣,知道原因的麻煩給我留言,非常感謝。我也在Unity論壇里提問里。

    我們看到很多成功的移動游戲,它們的畫面效果看起來好像包含了很多光源,但其實這都是騙人的。

    使用Lightmaps


    Lightmaps的很常見的一種優化策略。它主要用于場景中整體的光照效果。這種技術主要是提前把場景中的光照信息存儲在一張光照紋理中,然后在運行時刻只需要根據紋理采樣得到光照信息即可。
    當然與之配合的還有Light Probes技術。風宇沖有一個系列文章講過,但是時間比較久遠,但教程我相信網上有很多。

    使用God Rays


    場景中很多小型光源效果都是靠這種方法模擬的。它們一般并不是真的光源產生的,很多情況是通過透明紋理進行模擬。具體可以參見之前的文章。


    CPU優化

    減少Draw Calls


    批處理(Batching)


    這方面的優化教程想必是最多的了。最常見的就是通過批處理(Batching)了。從名字上來理解,就是一塊處理多個物體的意思。那么什么樣的物體可以一起處理呢?答案就是使用同一個材質的物體。這是因此,對于使用同一個材質的物體,它們之間的不同僅僅在于頂點數據的差別,即使用的網格不同而已。我們可以把這些頂點數據合并在一起,再一起發送給GPU,就可以完成一次批處理。
    Unity中有兩種批處理方式:一種是動態批處理,一種是靜態批處理。對于動態批處理來說,好消息是一切處理都是自動的,不需要我們自己做任何操作,而且物體是可以移動的,但壞消息是,限制很多,可能一不小心我們就會破壞了這種機制,導致Unity無法批處理一些使用了相同材質的物體。對于靜態批處理來說,好消息是自由度很高,限制很少,壞消息是可能會占用更多的內存,而且經過靜態批處理后的所有物體都不可以再移動了。
    首先來說動態批處理。Unity進行動態批處理的條件是,物體使用同一個材質并且滿足一些特定條件。Unity總是在不知不覺中就為我們做了動態批處理。例如下面的場景:



    這個場景共包含了4個物體,其中兩個箱子使用了同一個材質。可以看到,它的Draw Calls現在是3,并且顯示Save by batching是1,也就是說,Unity靠Batching為我們節省了1個Draw Call。下面,我們來把其中一個箱子的大小隨便改動一下,看看會發生什么:


    可以發現,Draw Calls變成了4,Save by batching的數目也變成了0。這是為什么呢?它們明明還是只使用了一個材質啊。原因就是前面提到的那些需要滿足的其他條件。動態批處理雖然自動得令人感動,但它對模型的要求很多:
    • 頂點屬性的最大限制為900,而且未來有可能會變。不要依賴這個數據。

    • 一般來說,那么所有對象都必須需要使用同一個縮放尺度(可以是(1, 1, 1)、(1, 2, 3)、(1.5, 1.4, 1.3)等等,但必須都一樣)。但如果是非統一縮放(即每個維度的縮放尺度不一樣,例如(1, 2, 1)),那么如果所有的物體都使用不同的非統一縮放也是可以批處理的。這個要求很怪異,為什么批處理會和縮放有關呢?這和Unity背后的技術有關系,有興趣的可以自行谷歌,比如這里。

    • 使用lightmap的物體不會批處理。多passes的shader會中斷批處理。接受實時陰影的物體也不會批處理。

    上述除了最常見的由于縮放導致破壞批處理的情況,還有就是頂點屬性的限制。例如,在上面的場景中我們添加之前未優化后的箱子模型:


    可以看到Draw Calls一下子變成了5。這是因為新添加的箱子模型中,包含了474個頂點,而它使用的頂點屬性有位置、UV坐標、法線等信息,使用的總和超過了900。

    動態批處理的條件這么多,一不小心它就不干了,因此Unity提供了另一個方法,靜態批處理。接著上面的例子,我們保持修改后的縮放,但把四個物體的“Static Flag”勾選上:

    點擊Static后面的三角下拉框,我們會看到其實這一步設置了很多東西,這里我們想要的只是“Batching static”一項。這時我們再看Draw Calls,恩,還是沒有變化。但是不要急,我們點擊運行,變化出現了:


    Draw Calls又回到了3,并且顯示Save by batching是1。這就是得利于靜態批處理。而且,如果我們在運行時刻查看模型的網格,會發現它們都變成了一個名為Combined Mesh (roo: scene)的東西。這個網格是Unity合并了所有標識為“Static”的物體的結果,在我們的例子里,就是四個物體:



    你可以要問了,這四個對象明明不是都使用了一個材質,為什么可以合并成一個呢?如果你仔細觀察上圖的話,會發現里面標明了“4 submeshes”,也就是說,這個合并后的網格其實包含了4個子網格,也就是我們的四個對象。對于合并后后的網格,Unity會判斷其中使用同一個材質的子網格,然后對它們進行批處理。
    但是,我們再細心點可以發現,我們的箱子使用的其實是同一個網格,但合并后卻變成了兩個。而且,我們觀察運行前后Stats窗口中的“VBO total”,它的大小由241.6KB變成了286.2KB,變大了!還記得靜態批處理的缺點嗎?就是可能會占用更多的內存。文檔中是這樣寫的:
    “Using static batching will require additional memory for storing the combined geometry. If several objects shared the same geometry before static batching, then a copy of geometry will be created for each object, either in the Editor or at runtime. This might not always be a good idea - sometimes you will have to sacrifice rendering performance by avoiding static batching for some objects to keep a smaller memory footprint. For example, marking trees as static in a dense forest level can have serious memory impact.”


    也就是說,如果在靜態批處理前有一些物體共享了相同的網格(例如這里的兩個箱子),那么每一個物體都會有一個該網格的復制品,即一個網格會變成多個網格被發送給GPU。在上面的例子看來,就是VBO的大小明顯增大了。如果這類使用同一網格的對象很多,那么這就是一個問題了,這種時候我們可能需要避免使用靜態批處理,這意味著犧牲一定的渲染性能。例如,如果在一個使用了1000個重復樹模型的森林中使用靜態批處理,那么結果就會產生1000倍的內存,這會造成嚴重的內存影響。這種時候,解決方法要么我們可以忍受這種犧牲內存換取性能的方法,要么不要使用靜態批處理,而使用動態批處理(前提是大家使用相同的縮放大小,或者大家都使用不同的非統一縮放大小),或者自己編寫批處理的方法。當然,我認為最好的還是使用動態批處理來解決。
    有一些小提示可以使用:
    • 盡可能選擇靜態批處理,但得時刻小心對內存的消耗。

    • 如果無法進行靜態批處理,而要使用動態批處理的話,那么請小心上面提到的各種注意事項。例如:

      • 盡可能讓這樣的物體少并且盡可能讓這些物體包含少量的頂點屬性。

      • 不要使用統一縮放,或者都使用不同的非統一縮放。

    • 對于游戲中的小道具,例如可以撿拾的金幣等,可以使用動態批處理。

    • 對于包含動畫的這類物體,我們無法全部使用靜態批處理,但其中如果有不動的部分,可以把這部分標識成“Static”。


    一些討論:
    How static batching works

    Static batching use a ton of memory?

    Unity3D draw call optimization

    合并紋理(Atlas)


    雖然批處理是個很好的方式,但很容易就打破它的規定。例如,場景中的物體都使用Diffuse材質,但它們可能會使用不同的紋理。因此,盡可能把多張小紋理合并到一張大紋理(Atlas)中是一個好主意。

    利用網格的頂點數據


    但有時,除了紋理不同外,還有對于不同的物體,它們在材質上還有一些微小的參數變化,例如顏色不同、某些浮點參數不同。但鐵定律是,不管是動態批處理還是靜態批處理,它們的前提都是要使用同一個材質。是同一個,而不是同一種,也就是說它們指向的材質必須是同一個實體。這意味著,只要我們調整了參數,就會影響到所有使用這個材質的對象。那么想要微小的調整怎么辦呢?由于Unity中的規定非常死,那么我們只好想些“歪門邪道”,其中一種就是使用網格的頂點數據(最常見的就是頂點顏色數據)。
    前面說過,經過批處理后的物體會被處理成一個VBO發送給GPU,VBO中的數據可以作為輸入傳遞給Vertex Shader,因此我們可以巧妙地對VBO中的數據進行控制,從而達到不同效果的目的。一個例子是,還是之前的森林,所有的樹使用了同一種材質,我們希望它們可以通過動態批處理來實現,但不同樹的顏色可能不同。這時我么可以利用網格的頂點數據來調整。具體方法,可以參見后面會寫的一篇文章。
    但這種方法的缺點就是會需要更多的內存來存儲這些用于調整參數用的頂點數據。沒辦法,永遠沒有絕對完美的方法。


    帶寬優化

    減少紋理大小


    之前提到過,使用Texture Atlas可以幫助減少Draw Calls,而這些紋理的大小同樣是一個需要考慮的問題。在這之前要提到一個問題就是,所有紋理的長寬比最好是正方形,而且長度值最好是2的整數冪。這是因為有很多優化策略只有在這種時候才可以發揮最大效用。
    Unity中查看紋理參數可以通過紋理的面板:


    而調整參數可以通過紋理的Advance面板:



    上面各種參數的說明可以參見文檔。其中和優化相關的主要有“Generate Mip Maps”、“Max Size”和“Format”幾個選項。
    “Generate Mip Maps”會為同一張紋理創建出很多不同大小的小紋理,構成一個紋理金字塔。而在游戲中可以根據距離物體的遠近,來動態選擇使用哪一個紋理。這是因為,在距離物體很遠的時候,就算我們使用了非常精細的紋理,但肉眼也是分辨不出來的,這種時候完全可以使用更小、更模糊的紋理來代替,而這大量可以節省訪問的像素的數目。但它的缺點是,由于需要為每一個紋理建立一個圖像金字塔,因此它會需要占用更多的內存。例如上面的例子,在勾選“Generate Mip Maps”前,內存占用是0.5M,而勾選了“Generate Mip Maps”后,就變成了0.7M。除了內存的占用以外,一些時候我們也不希望使用Mipmaps,例如GUI紋理等。我們還可以在面板中查看生成的Mip Maps:



    Unity中還提供了查看場景中物體的Mip Maps的使用情況。更確切的說是,展示了物體理想的紋理大小。其中紅色表示這個物體可以使用更小的紋理,藍色表示應該使用更大的紋理。


    “Max Size”決定了紋理的長寬值,如果我們使用的紋理本身超過了這個最大值,Unity會對其進行縮小來滿足這個條件。這里再重復一點,所有紋理的長寬比最好是正方形,而且長度值最好是2的整數冪。這是因為有很多優化策略只有在這種時候才可以發揮最大效用。
    “Format”負責紋理使用的壓縮模式。通常選擇這種自動模式就可以了,Unity會負責根據不同的平臺來選擇合適的壓縮模式。而對于GUI類型的紋理,我們可以根據對畫質的要求來選擇是否進行壓縮,具體可以參見之前關于畫質的文章。


    我們還可以根據不同的機器來選擇使用不同分辨率的紋理,以便讓游戲在某些老機器上也可以運行。

    利用縮放


    很多時候分辨率也是造成性能下降的原因,尤其是現在很多國內山寨機,除了分辨率高其他硬件簡直一塌糊涂,而這恰恰中了游戲性能的兩個瓶頸:過大的屏幕分辨率+糟糕的GPU。因此,我們可能需要對于特定機器進行分辨率的放縮。當然,這樣會造成游戲效果的下降,但性能和畫面之間永遠是個需要權衡的話題。
    在Unity中設置屏幕分辨率可以直接調用Screen.SetResolution。實際使用中可能會遇到一些情況,雨松MOMO有一篇文章講了這種技術,可以去看看。
    ?

    寫在最后


    這篇文章是總結性質的,因此對每種技術都沒有進行非常詳細的解釋。強烈建議大家閱讀文章開頭給出的各種鏈接,寫得都很好。

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    剛開始寫這篇文章的時候選了一個很土的題目。。。《Unity3D優化全解析》。因為這是一篇臨時起意才寫的文章,而且陳述的都是既有的事實,因而給自己“文(dou)學(bi)”加工留下的余地就少了很多。但又覺得這塊是不得不提的一個地方,平時見到很多人對此處也給予了忽略了事,需要時才去網上扒一些只言片語的資料。也恰逢年前,尋思著周末認真寫點東西遇到節假日沒準也沒什么人讀,所以索性就寫了這篇臨時的文章。題目很土,因為用了指向性很明確的“Unity3D”,讓人少了遐(瞎)想的空間,同時用了“高大全”這樣的構詞法,也讓匹夫有成為眾矢之的的可能。。。所以最后還是改成了現在各位看到的題目。話不多說,下面就開始正文~正所謂“草蛇灰線,伏脈千里”。那咱們首先~~~~~~

    看看優化需要從哪里著手?

    匹夫印象里遇到的童靴,提Unity3D項目優化則必提DrawCall,這自然沒錯,但也有很不好影響。因為這會給人一個錯誤的認識:所謂的優化就是把DrawCall弄的比較低就對了。

    對優化有這種第一印象的人不在少數,drawcall的確是一個很重要的指標,但絕非全部。為了讓各位和匹夫能達成盡可能多的共識,匹夫首先介紹一下本文可能會涉及到的幾個概念,之后會提出優化所涉及的三大方面:

    • drawcall是啥?其實就是對底層圖形程序(比如:OpenGL ES)接口的調用,以在屏幕上畫出東西。所以,是誰去調用這些接口呢?CPU。
    • fragment是啥?經常有人說vf啥的,vertex我們都知道是頂點,那fragment是啥呢?說它之前需要先說一下像素,像素各位應該都知道吧?像素是構成數碼影像的基本單元呀。那fragment呢?是有可能成為像素的東西。啥叫有可能?就是最終會不會被畫出來不一定,是潛在的像素。這會涉及到誰呢?GPU。
    • batching是啥?都知道批處理是干嘛的吧?沒錯,將批處理之前需要很多次調用(drawcall)的物體合并,之后只需要調用一次底層圖形程序的接口就行。聽上去這簡直就是優化的終極方案啊!但是,理想是美好的,世界是殘酷的,一些不足之后我們再細聊。
    • 內存的分配:記住,除了Unity3D自己的內存損耗。我們可是還帶著Mono呢啊,還有托管的那一套東西呢。更別說你一激動,又引入了自己的幾個dll。這些都是內存開銷上需要考慮到的。

    好啦,文中的幾個概念提前講清楚了,其實各位也能看的出來匹夫接下來要說的匹夫關注的優化時需要注意的方面:

    • CPU方面
    • GPU方面
    • 內存方面

    所以,這篇文章也會按照CPU—->GPU—->內存的順序進行。

    CPU的方面的優化:

    上文中說了,drawcall影響的是CPU的效率,而且也是最知名的一個優化點。但是除了drawcall之外,還有哪些因素也會影響到CPU的效率呢?讓我們一一列出暫時能想得到的:

    • DrawCalls
    • 物理組件(Physics)
    • GC(什么?GC不是處理內存問題的嘛?匹夫你不要騙我啊!不過,匹夫也要提醒一句,GC是用來處理內存的,但是是誰使用GC去處理內存的呢?)
    • 當然,還有代碼質量

    DrawCalls:

    前面說過了,DrawCall是CPU調用底層圖形接口。比如有上千個物體,每一個的渲染都需要去調用一次底層接口,而每一次的調用CPU都需要做很多工作,那么CPU必然不堪重負。但是對于GPU來說,圖形處理的工作量是一樣的。所以對DrawCall的優化,主要就是為了盡量解放CPU在調用圖形接口上的開銷。所以針對drawcall我們主要的思路就是每個物體盡量減少渲染次數,多個物體最好一起渲染。所以,按照這個思路就有了以下幾個方案:

  • 使用Draw Call Batching,也就是描繪調用批處理。Unity在運行時可以將一些物體進行合并,從而用一個描繪調用來渲染他們。具體下面會介紹。
  • 通過把紋理打包成圖集來盡量減少材質的使用。
  • 盡量少的使用反光啦,陰影啦之類的,因為那會使物體多次渲染。
  • Draw Call Batching

    首先我們要先理解為何2個沒有使用相同材質的物體即使使用批處理,也無法實現Draw Call數量的下降和性能上的提升。

    因為被“批處理”的2個物體的網格模型需要使用相同材質的目的,在于其紋理是相同的,這樣才可以實現同時渲染的目的。因而保證材質相同,是為了保證被渲染的紋理相同。

    因此,為了將2個紋理不同的材質合二為一,我們就需要進行上面列出的第二步,將紋理打包成圖集。具體到合二為一這種情況,就是將2個紋理合成一個紋理。這樣我們就可以只用一個材質來代替之前的2個材質了。

    而Draw Call Batching本身,也還會細分為2種。

    Static Batching 靜態批處理

    看名字,猜使用的情景。

    靜態?那就是不動的咯。還有呢?額,聽上去狀態也不會改變,沒有“生命”,比如山山石石,樓房校舍啥的。那和什么比較類似呢?嗯,聰明的各位一定覺得和場景的屬性很像吧!所以我們的場景似乎就可以采用這種方式來減少draw call了。

    那么寫個定義:只要這些物體不移動,并且擁有相同的材質,靜態批處理就允許引擎對任意大小的幾何物體進行批處理操作來降低描繪調用。

    那要如何使用靜態批來減少Draw Call呢?你只需要明確指出哪些物體是靜止的,并且在游戲中永遠不會移動、旋轉和縮放。想完成這一步,你只需要在檢測器(Inspector)中將Static復選框打勾即可,如下圖所示:

    至于效果如何呢?

    舉個例子:新建4個物體,分別是Cube,Sphere, Capsule, Cylinder,它們有不同的網格模型,但是也有相同的材質(Default-Diffuse)。

    首先,我們不指定它們是static的。Draw Call的次數是4次,如圖:

    我們現在將它們4個物體都設為static,在來運行一下:

    如圖,Draw Call的次數變成了1,而Saved by batching的次數變成了3。

    靜態批處理的好處很多,其中之一就是與下面要說的動態批處理相比,約束要少很多。所以一般推薦的是draw call的靜態批處理來減少draw call的次數。那么接下來,我們就繼續聊聊draw call的動態批處理。

    Dynamic Batching 動態批處理

    有陰就有陽,有靜就有動,所以聊完了靜態批處理,肯定跟著就要說說動態批處理了。首先要明確一點,Unity3D的draw call動態批處理機制是引擎自動進行的,無需像靜態批處理那樣手動設置static。我們舉一個動態實例化prefab的例子,如果動態物體共享相同的材質,則引擎會自動對draw call優化,也就是使用批處理。首先,我們將一個cube做成prefab,然后再實例化500次,看看draw call的數量。

    12345for(int i = 0; i < 500; i++){????GameObject cube;????cube = GameObject.Instantiate(prefab) as GameObject;}

    draw call的數量:

    可以看到draw call的數量為1,而 saved by batching的數量是499。而這個過程中,我們除了實例化創建物體之外什么都沒做。不錯,unity3d引擎為我們自動處理了這種情況。

    但是有很多童靴也遇到這種情況,就是我也是從prefab實例化創建的物體,為何我的draw call依然很高呢?這就是匹夫上文說的,draw call的動態批處理存在著很多約束。下面匹夫就演示一下,針對cube這樣一個簡單的物體的創建,如果稍有不慎就會造成draw call飛漲的情況吧。

    我們同樣是創建500個物體,不同的是其中的100個物體,每個物體的大小都不同,也就是Scale不同。

    1 2 3 4 5 6 7 8 9 for(int i = 0; i < 500; i++) { ????GameObject cube; ????cube = GameObject.Instantiate(prefab) as GameObject; ????if(i / 100 == 0) ????{ ????????cube.transform.localScale = new Vector3(2 + i, 2 + i, 2 + i); ????} }

    draw call的數量:

    我們看到draw call的數量上升到了101次,而saved by batching的數量也下降到了399。各位看官可以看到,僅僅是一個簡單的cube的創建,如果scale不同,竟然也不會去做批處理優化。這僅僅是動態批處理機制的一種約束,那我們總結一下動態批處理的約束,各位也許也能從中找到為何動態批處理在自己的項目中不起作用的原因:

  • 批處理動態物體需要在每個頂點上進行一定的開銷,所以動態批處理僅支持小于900頂點的網格物體。
  • 如果你的著色器使用頂點位置,法線和UV值三種屬性,那么你只能批處理300頂點以下的物體;如果你的著色器需要使用頂點位置,法線,UV0,UV1和切向量,那你只能批處理180頂點以下的物體。
  • 不要使用縮放。分別擁有縮放大小(1,1,1) 和(2,2,2)的兩個物體將不會進行批處理。
  • 統一縮放的物體不會與非統一縮放的物體進行批處理。
  • 使用縮放尺度(1,1,1) 和 (1,2,1)的兩個物體將不會進行批處理,但是使用縮放尺度(1,2,1) 和(1,3,1)的兩個物體將可以進行批處理。
  • 使用不同材質的實例化物體(instance)將會導致批處理失敗。
  • 擁有lightmap的物體含有額外(隱藏)的材質屬性,比如:lightmap的偏移和縮放系數等。所以,擁有lightmap的物體將不會進行批處理(除非他們指向lightmap的同一部分)。
  • 多通道的shader會妨礙批處理操作。比如,幾乎unity中所有的著色器在前向渲染中都支持多個光源,并為它們有效地開辟多個通道。
  • 預設體的實例會自動地使用相同的網格模型和材質。
  • 所以,盡量使用靜態的批處理。

    物理組件

    曾幾何時,匹夫在做一個策略類游戲的時候需要在單元格上排兵布陣,而要偵測到哪個兵站在哪個格子匹夫選擇使用了射線,由于士兵單位很多,而且為了精確每一幀都會執行檢測,那時候CPU的負擔叫一個慘不忍睹。后來匹夫果斷放棄了這種做法,并且對物理組件產生了心理的陰影。

    這里匹夫只提2點匹夫感覺比較重要的優化措施:

    1.設置一個合適的Fixed Timestep。設置的位置如圖:

    那何謂“合適”呢?首先我們要搞明白Fixed Timestep和物理組件的關系。物理組件,或者說游戲中模擬各種物理效果的組件,最重要的是什么呢?計算啊。對,需要通過計算才能將真實的物理效果展現在虛擬的游戲中。那么Fixed Timestep這貨就是和物理計算有關的啦。所以,若計算的頻率太高,自然會影響到CPU的開銷。同時,若計算頻率達不到游戲設計時的要求,有會影響到功能的實現,所以如何抉擇需要各位具體分析,選擇一個合適的值。

    2.就是不要使用網格碰撞器(mesh collider):為啥?因為實在是太復雜了。網格碰撞器利用一個網格資源并在其上構建碰撞器。對于復雜網狀模型上的碰撞檢測,它要比應用原型碰撞器精確的多。標記為凸起的(Convex )的網格碰撞器才能夠和其他網格碰撞器發生碰撞。各位上網搜一下mesh collider的圖片,自然就會明白了。我們的手機游戲自然無需這種性價比不高的東西。

    當然,從性能優化的角度考慮,物理組件能少用還是少用為好。

    處理內存,卻讓CPU受傷的GC

    在CPU的部分聊GC,感覺是不是怪怪的?其實小匹夫不這么覺得,雖然GC是用來處理內存的,但的確增加的是CPU的開銷。因此它的確能達到釋放內存的效果,但代價更加沉重,會加重CPU的負擔,因此對于GC的優化目標就是盡量少的觸發GC。

    首先我們要明確所謂的GC是Mono運行時的機制,而非Unity3D游戲引擎的機制,所以GC也主要是針對Mono的對象來說的,而它管理的也是Mono的托管堆。 搞清楚這一點,你也就明白了GC不是用來處理引擎的assets(紋理啦,音效啦等等)的內存釋放的,因為U3D引擎也有自己的內存堆而不是和Mono一起使用所謂的托管堆。

    其次我們要搞清楚什么東西會被分配到托管堆上?不錯咯,就是引用類型咯。比如類的實例,字符串,數組等等。而作為int,float,包括結構體struct其實都是值類型,它們會被分配在堆棧上而非堆上。所以我們關注的對象無外乎就是類實例,字符串,數組這些了。

    那么GC什么時候會觸發呢?兩種情況:

  • 首先當然是我們的堆的內存不足時,會自動調用GC。
  • 其次呢,作為編程人員,我們自己也可以手動的調用GC。
  • 所以為了達到優化CPU的目的,我們就不能頻繁的觸發GC。而上文也說了GC處理的是托管堆,而不是Unity3D引擎的那些資源,所以GC的優化說白了也就是代碼的優化。那么匹夫覺得有以下幾點是需要注意的:

  • 字符串連接的處理。因為將兩個字符串連接的過程,其實是生成一個新的字符串的過程。而之前的舊的字符串自然而然就成為了垃圾。而作為引用類型的字符串,其空間是在堆上分配的,被棄置的舊的字符串的空間會被GC當做垃圾回收。
  • 盡量不要使用foreach,而是使用for。foreach其實會涉及到迭代器的使用,而據傳說每一次循環所產生的迭代器會帶來24 Bytes的垃圾。那么循環10次就是240Bytes。
  • 不要直接訪問gameobject的tag屬性。比如if (go.tag == “human”)最好換成if (go.CompareTag (“human”))。因為訪問物體的tag屬性會在堆上額外的分配空間。如果在循環中這么處理,留下的垃圾就可想而知了。
  • 使用“池”,以實現空間的重復利用。
  • 最好不用LINQ的命令,因為它們會分配臨時的空間,同樣也是GC收集的目標。而且我很討厭LINQ的一點就是它有可能在某些情況下無法很好的進行AOT編譯。比如“OrderBy”會生成內部的泛型類“OrderedEnumerable”。這在AOT編譯時是無法進行的,因為它只是在OrderBy的方法中才使用。所以如果你使用了OrderBy,那么在IOS平臺上也許會報錯。
  • 代碼?腳本?

    聊到代碼這個話題,也許有人會覺得匹夫多此一舉。因為代碼質量因人而異,很難像上面提到的幾點,有一個明確的評判標準。也是,公寫公有理,婆寫婆有理。但是匹夫這里要提到的所謂代碼質量是基于一個前提的:Unity3D是用C++寫的,而我們的代碼是用C#作為腳本來寫的,那么問題就來了~腳本和底層的交互開銷是否需要考慮呢?也就是說,我們用Unity3D寫游戲的“游戲腳本語言”,也就是C#是由mono運行時托管的。而功能是底層引擎的C++實現的,“游戲腳本”中的功能實現都離不開對底層代碼的調用。那么這部分的開銷,我們應該如何優化呢?

    1.以物體的Transform組件為例,我們應該只訪問一次,之后就將它的引用保留,而非每次使用都去訪問。這里有人做過一個小實驗,就是對比通過方法GetComponent<Transform>()獲取Transform組件, 通過MonoBehavor的transform屬性去取,以及保留引用之后再去訪問所需要的時間:

    • GetComponent = 619ms
    • Monobehaviour = 60ms
    • CachedMB = 8ms
    • Manual Cache = 3ms

    2.如上所述,最好不要頻繁使用GetComponent,尤其是在循環中。

    3.善于使用OnBecameVisible()和OnBecameVisible(),來控制物體的update()函數的執行以減少開銷。

    4.使用內建的數組,比如用Vector3.zero而不是new Vector(0, 0, 0);

    5.對于方法的參數的優化:善于使用ref關鍵字。值類型的參數,是通過將實參的值復制到形參,來實現按值傳遞到方法,也就是我們通常說的按值傳遞。復制嘛,總會讓人感覺很笨重。比如Matrix4x4這樣比較復雜的值類型,如果直接復制一份新的,反而不如將值類型的引用傳遞給方法作為參數。

    好啦,CPU的部分匹夫覺得到此就介紹的差不多了。下面就簡單聊聊其實匹夫并不是十分熟悉的部分,GPU的優化。

    GPU的優化

    GPU與CPU不同,所以側重點自然也不一樣。GPU的瓶頸主要存在在如下的方面:

  • 填充率,可以簡單的理解為圖形處理單元每秒渲染的像素數量。
  • 像素的復雜度,比如動態陰影,光照,復雜的shader等等
  • 幾何體的復雜度(頂點數量)
  • 當然還有GPU的顯存帶寬
  • 那么針對以上4點,其實仔細分析我們就可以發現,影響的GPU性能的無非就是2大方面,一方面是頂點數量過多,像素計算過于復雜。另一方面就是GPU的顯存帶寬。那么針鋒相對的兩方面舉措也就十分明顯了。

  • 少頂點數量,簡化計算復雜度。
  • 縮圖片,以適應顯存帶寬。
  • 減少繪制的數目

    那么第一個方面的優化也就是減少頂點數量,簡化復雜度,具體的舉措就總結如下了:

    • 保持材質的數目盡可能少。這使得Unity更容易進行批處理。
    • 使用紋理圖集(一張大貼圖里包含了很多子貼圖)來代替一系列單獨的小貼圖。它們可以更快地被加載,具有很少的狀態轉換,而且批處理更友好。
    • 如果使用了紋理圖集和共享材質,使用Renderer.sharedMaterial?來代替Renderer.material?。
    • 使用光照紋理(lightmap)而非實時燈光。
    • 使用LOD,好處就是對那些離得遠,看不清的物體的細節可以忽略。
    • 遮擋剔除(Occlusion culling)
    • 使用mobile版的shader。因為簡單。

    優化顯存帶寬

    第二個方向呢?壓縮圖片,減小顯存帶寬的壓力。

    • OpenGL ES 2.0使用ETC1格式壓縮等等,在打包設置那里都有。
    • 使用mipmap。

    MipMap

    這里匹夫要著重介紹一下MipMap到底是啥。因為有人說過MipMap會占用內存呀,但為何又會優化顯存帶寬呢?那就不得不從MipMap是什么開始聊起。一張圖其實就能解決這個疑問。

    上面是一個mipmap 如何儲存的例子,左邊的主圖伴有一系列逐層縮小的備份小圖

    是不是很一目了然呢?Mipmap中每一個層級的小圖都是主圖的一個特定比例的縮小細節的復制品。因為存了主圖和它的那些縮小的復制品,所以內存占用會比之前大。但是為何又優化了顯存帶寬呢?因為可以根據實際情況,選擇適合的小圖來渲染。所以,雖然會消耗一些內存,但是為了圖片渲染的質量(比壓縮要好),這種方式也是推薦的。

    內存的優化

    既然要聊Unity3D運行時候的內存優化,那我們自然首先要知道Unity3D游戲引擎是如何分配內存的。大概可以分成三大部分:

  • Unity3D內部的內存
  • Mono的托管內存
  • 若干我們自己引入的DLL或者第三方DLL所需要的內存。
  • 第3類不是我們關注的重點,所以接下來我們會分別來看一下Unity3D內部內存和Mono托管內存,最后還將分析一個官網上Assetbundle的案例來說明內存的管理。

    Unity3D內部內存

    Unity3D的內部內存都會存放一些什么呢?各位想一想,除了用代碼來驅動邏輯,一個游戲還需要什么呢?對,各種資源。所以簡單總結一下Unity3D內部內存存放的東西吧:

    • 資源:紋理、網格、音頻等等
    • GameObject和各種組件。
    • 引擎內部邏輯需要的內存:渲染器,物理系統,粒子系統等等

    Mono托管內存

    因為我們的游戲腳本是用C#寫的,同時還要跨平臺,所以帶著一個Mono的托管環境顯然必須的。那么Mono的托管內存自然就不得不放到內存的優化范疇中進行考慮。那么我們所說的Mono托管內存中存放的東西和Unity3D內部內存中存放的東西究竟有何不同呢?其實Mono的內存分配就是很傳統的運行時內存的分配了:

    • 值類型:int型啦,float型啦,結構體struct啦,bool啦之類的。它們都存放在堆棧上(注意額,不是堆所以不涉及GC)。
    • 引用類型:其實可以狹義的理解為各種類的實例。比如游戲腳本中對游戲引擎各種控件的封裝。其實很好理解,C#中肯定要有對應的類去對應游戲引擎中的控件。那么這部分就是C#中的封裝。由于是在堆上分配,所以會涉及到GC。

    而Mono托管堆中的那些封裝的對象,除了在在Mono托管堆上分配封裝類實例化之后所需要的內存之外,還會牽扯到其背后對應的游戲引擎內部控件在Unity3D內部內存上的分配。

    舉一個例子:

    一個在.cs腳本中聲明的WWW類型的對象www,Mono會在Mono托管堆上為www分配它所需要的內存。同時,這個實例對象背后的所代表的引擎資源所需要的內存也需要被分配。

    一個WWW實例背后的資源:

    • 壓縮的文件
    • 解壓縮所需的緩存
    • 解壓縮之后的文件

    如圖:

    那么下面就舉一個AssetBundle的例子:

    Assetbundle的內存處理

    以下載Assetbundle為例子,聊一下內存的分配。匹夫從官網的手冊上找到了一個使用Assetbundle的情景如下:

    123456789101112131415161718192021IEnumerator DownloadAndCache (){????????// Wait for the Caching system to be ready????????while (!Caching.ready)????????????yield return null;????????// Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache????????using(WWW www = WWW.LoadFromCacheOrDownload (BundleURL, version)){????????????yield return www; //WWW是第1部分????????????if (www.error != null)????????????????throw new Exception(&quot;WWW download had an error:&quot; + www.error);????????????AssetBundle bundle = www.assetBundle;//AssetBundle是第2部分????????????if (AssetName == &quot;&quot;)????????????????Instantiate(bundle.mainAsset);//實例化是第3部分????????????else????????????????Instantiate(bundle.Load(AssetName));????????????????????// Unload the AssetBundles compressed contents to conserve memory????????????????????bundle.Unload(false);????????} // memory is freed from the web stream (www.Dispose() gets called implicitly)????}}

    內存分配的三個部分匹夫已經在代碼中標識了出來:

  • Web Stream:包括了壓縮的文件,解壓所需的緩存,以及解壓后的文件。
  • AssetBundle:Web Stream中的文件的映射,或者說引用。
  • 實例化之后的對象就是引擎的各種資源文件了,會在內存中創建出來。
  • 那就分別解析一下:

    1 WWW www = WWW.LoadFromCacheOrDownload (BundleURL, version)

  • 將壓縮的文件讀入內存中
  • 創建解壓所需的緩存
  • 將文件解壓,解壓后的文件進入內存
  • 關閉掉為解壓創建的緩存
  • 1AssetBundle bundle = www.assetBundle;

  • AssetBundle此時相當于一個橋梁,從Web Stream解壓后的文件到最后實例化創建的對象之間的橋梁。
  • 所以AssetBundle實質上是Web Stream解壓后的文件中各個對象的映射。而非真實的對象。
  • 實際的資源還存在Web Stream中,所以此時要保留Web Stream。
  • 1 Instantiate(bundle.mainAsset);

    通過AssetBundle獲取資源,實例化對象

    最后各位可能看到了官網中的這個例子使用了:

    12using(WWW www = WWW.LoadFromCacheOrDownload (BundleURL, version)){}

    這種using的用法。這種用法其實就是為了在使用完Web Stream之后,將內存釋放掉的。因為WWW也繼承了idispose的接口,所以可以使用using的這種用法。其實相當于最后執行了:

    1 2 //刪除Web Stream www.Dispose();

    OK,Web Stream被刪除掉了。那還有誰呢?對Assetbundle。那么使用

    1 2 //刪除AssetBundle bundle.Unload(false);

    ok,寫到這里就先打住啦。寫的有點超了。有點趕也有點臨時,日后在補充編輯。



    總結

    以上是生活随笔為你收集整理的unity3d优化收集摘录的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    日韩高清激情 | 精品国产99国产精品 | 美女精品久久久 | 国产分类视频 | 精品一二三区视频 | 欧美日韩在线观看一区二区 | 久久久黄视频 | 久久久久成人精品 | 国产一区 在线播放 | 久久久久久久久久久久影院 | 欧美精品久久久 | 99视频网址| 国产精品久久久久久久久蜜臀 | 一区二区激情 | 开心丁香婷婷深爱五月 | 欧美精品久久人人躁人人爽 | 国产精品成人一区二区三区吃奶 | 国产91小视频| 中文在线字幕免费观看 | 久久69av| 成人小视频免费在线观看 | 97av视频 | 国产美女在线精品免费观看 | 国产精品久久久久国产精品日日 | 2023av在线 | 国产91aaa | 最近日本韩国中文字幕 | 青青草视频精品 | 国产精品小视频网站 | 日日操日日| 久久亚洲免费 | 国产精品理论视频 | av黄色av| 在线观看视频在线观看 | 久久九九视频 | 91av在线播放 | 亚洲精品中文字幕在线观看 | 久久久久久久久久久高潮一区二区 | freejavvideo日本免费 | 麻豆国产在线播放 | 欧美一级激情 | 91大神电影 | 欧美射射射 | 欧美性高跟鞋xxxxhd | 午夜性色| 国产精品久久久久久影院 | 91精品国产综合久久福利不卡 | 日韩一级片大全 | 91精品办公室少妇高潮对白 | 天堂视频中文在线 | 亚洲国产三级在线 | 91成人免费在线 | 久久亚洲影院 | 久久超碰网 | 日韩v在线91成人自拍 | 国产片免费在线观看视频 | 在线视频欧美日韩 | 欧美日韩一区二区在线观看 | 久久久久观看 | 日b视频在线观看网址 | 96av在线| 天天天干夜夜夜操 | 欧美在一区 | 97色在线观看 | 免费高清av在线看 | 国产精品国产三级在线专区 | 欧美一区二视频在线免费观看 | 婷婷丁香激情 | 国产小视频免费观看 | 一本一道久久a久久精品蜜桃 | 亚洲成人av一区二区 | 日本福利视频在线 | 国产黄色一级大片 | 成人国产一区二区 | av电影免费看| 亚洲激情影院 | 国产日韩视频在线 | 国产精品欧美久久久久三级 | 亚洲黄色一级大片 | 91精品久久久久久综合五月天 | 日韩欧美高清视频在线观看 | 国产欧美最新羞羞视频在线观看 | 日韩在线欧美在线 | 青青视频一区 | 免费看三级网站 | 国产99视频在线观看 | 久久久精品网站 | japanesexxxxfreehd乱熟| 99精品国产99久久久久久97 | www黄色| 97超碰在线久草超碰在线观看 | 久久久久久久综合色一本 | 黄色精品视频 | 色综合亚洲精品激情狠狠 | 97在线免费视频 | 综合天天 | 久久黄色免费观看 | 国产精品久久久久久久久久直播 | 黄毛片在线观看 | 97电影在线看视频 | 激情视频在线观看网址 | 91在线看视频免费 | 久久草草热国产精品直播 | 亚洲精品www. | 91麻豆产精品久久久久久 | 99久视频| 99热国产精品 | a成人v在线 | 女人高潮一级片 | 综合久久五月天 | 成人亚洲精品久久久久 | 国产亚州精品视频 | 亚洲禁18久人片 | 久久精品九色 | 婷婷播播网| 一区二区三区视频网站 | 精品视频在线免费观看 | 在线观看深夜视频 | 久久久久久久久久久免费视频 | 欧美色图亚洲图片 | 亚洲乱码国产乱码精品天美传媒 | 国产尤物视频在线 | 国产二级视频 | 黄污在线看 | 国产不卡在线观看视频 | 亚洲一二三在线 | 500部大龄熟乱视频 欧美日本三级 | 福利片免费看 | 亚洲国产精品久久 | 国产第一二区 | 天天插天天 | av九九九| 中国一区二区视频 | 国产一级电影免费观看 | 精品你懂的 | 天天天色综合 | 日韩av不卡播放 | 伊人天堂av | 丁香婷婷网 | 成人免费中文字幕 | 精品久久久久久久久久久院品网 | 热久久精品在线 | 午夜精品中文字幕 | 亚洲精品乱码久久 | 亚洲第一中文字幕 | 日韩久久精品一区 | 又黄又爽又湿又无遮挡的在线视频 | 91香蕉视频在线下载 | 久久精品com| 亚洲艳情| 日韩欧美一区二区不卡 | 特黄特色特刺激视频免费播放 | 97超视频免费观看 | 欧美性生活大片 | 日本中文字幕影院 | 国产中文字幕视频 | 欧美美女激情18p | 国产高清av免费在线观看 | 国产91av视频在线观看 | www.亚洲黄色 | 国产一区国产精品 | 久草网在线 | 夜夜高潮夜夜爽国产伦精品 | 亚洲精品理论 | 最新精品视频在线 | 人成电影网 | av色综合| 天天综合成人 | 就要干b | 国产视频一二区 | 天天色天天色 | 国产成人av片 | 国产爽视频 | 午夜视频日本 | 国产精品激情偷乱一区二区∴ | 天堂在线v| 久久久久久久免费观看 | 中文字幕精品视频 | 国产精品福利午夜在线观看 | 久久精品国产久精国产 | 欧亚日韩精品一区二区在线 | 麻豆国产在线播放 | 欧美a在线看 | 在线91播放 | 久久久人人人 | 亚洲成av人影片在线观看 | 日本在线中文在线 | 99精品在线| 日韩一区二区三 | 亚洲精品久久久久58 | 91探花国产综合在线精品 | 最新国产精品拍自在线播放 | 亚洲美女在线国产 | 免费高清在线视频一区· | 色婷婷激情电影 | 国产aaa大片 | 午夜av免费看 | 国产一区影院 | 亚洲 综合 精品 | 久久久久久久久久久久久9999 | 黄色成人av| 国产精品18毛片一区二区 | 91在线欧美| 中文字幕一区二区三区乱码在线 | 亚洲手机天堂 | 五月婷婷综合在线观看 | 欧美在线视频精品 | 四虎在线观看精品视频 | 亚洲精品免费视频 | 亚洲理论片| 久艹视频免费观看 | 天天色天天综合网 | 99在线观看视频网站 | 国产婷婷久久 | 亚洲精品国产精品国自 | 在线天堂v| 在线成人免费电影 | 亚洲 成人 一区 | 国产精品一区二 | 成人毛片在线观看 | 国产福利91精品张津瑜 | 亚洲精品视频免费看 | 69国产盗摄一区二区三区五区 | av电影在线播放 | 天天操天天舔天天爽 | 亚洲午夜久久久久久久久电影网 | 高潮毛片无遮挡高清免费 | 激情欧美一区二区三区 | 精品国产一区二区三区久久久蜜月 | 国产在线自 | 九九国产精品视频 | 日本中文乱码卡一卡二新区 | 天天天天色综合 | 深爱五月激情网 | 四虎成人精品永久免费av九九 | 在线视频观看你懂的 | 国产色视频一区二区三区qq号 | 国产丝袜高跟 | 91成人看片 | 在线婷婷 | 欧美少妇xxxxxx | 久久国产精品99久久久久久进口 | 在线观看黄色 | 91免费试看 | 2018好看的中文在线观看 | 欧美一区二区三区在线视频观看 | 成人av高清 | 四虎成人免费观看 | 一区二区三区四区免费视频 | 98久久| 中文字幕色在线 | 91精品国产成 | 国产免费小视频 | 狠狠ri | 国产精品1区2区3区在线观看 | 国产一区电影在线观看 | 国产中文字幕在线播放 | 91成人精品在线 | 日韩亚洲精品电影 | 亚洲狠狠丁香婷婷综合久久久 | 极品久久久久 | 中文字幕亚洲欧美日韩 | 欧美日韩中文字幕综合视频 | 天天曰夜夜操 | 91香蕉国产在线观看软件 | 欧美日韩国产在线精品 | 97视频在线观看成人 | 欧美日韩视频网站 | 亚洲精品国产精品乱码不99热 | 免费看黄色小说的网站 | 手机av片| 久久成年人视频 | 成人一级片在线观看 | 4438全国亚洲精品在线观看视频 | 精品久久久久久久久久 | 4438全国亚洲精品在线观看视频 | 天堂视频一区 | 啪啪免费视频网站 | 欧美一区二区三区在线播放 | 香蕉视频最新网址 | 高清中文字幕av | 9在线观看免费 | 色婷丁香| 国产黄在线观看 | 国内视频在线观看 | 中文字幕在线字幕中文 | 国产精品自产拍在线观看 | 一区二区网 | 中文高清av| 在线观看日韩精品视频 | 欧美日韩精品免费观看视频 | 色资源二区在线视频 | 日韩视频一区二区三区在线播放免费观看 | 一区二区三区免费看 | bbb搡bbb爽爽爽 | 亚洲高清在线观看视频 | 美女久久视频 | 成人app在线免费观看 | 成人资源网 | 日日碰夜夜爽 | 国产第一页在线观看 | 狠狠地操 | 国产九九在线 | 中文字幕国产在线 | 五月婷网站 | 久久久久国产a免费观看rela | 99久久精品一区二区成人 | 综合网天天色 | 四虎国产精品永久在线国在线 | 国产黄色片在线 | 精品九九九 | 日韩一区在线播放 | 精品视频 | av中文在线观看 | 麻豆91小视频 | 天堂网在线视频 | 黄色网在线免费观看 | 亚洲六月丁香色婷婷综合久久 | 激情在线网站 | 国产又黄又爽又猛视频日本 | 九色自拍视频 | 天天草天天操 | 天天色中文 | 日日婷婷夜日日天干 | av亚洲产国偷v产偷v自拍小说 | 国产a网站 | 精品国产电影一区 | 美女网站视频久久 | 人人玩人人弄 | a视频免费 | 九九热免费视频在线观看 | 久久老司机精品视频 | 欧美日韩一区二区视频在线观看 | 99久e精品热线免费 99国产精品久久久久久久久久 | 久久精品日产第一区二区三区乱码 | 不卡的av片 | 国产成人精品一区二区在线观看 | 亚洲精品av在线 | 成人中心免费视频 | 在线免费av网站 | 久久亚洲二区 | 超碰在线98 | 亚洲在线精品 | 国产视频二区三区 | 亚洲成人av影片 | 成人黄色av网站 | 九九久久国产精品 | 欧美日韩国产mv | 美女视频永久黄网站免费观看国产 | 久久精品中文 | 国产精品国产亚洲精品看不卡15 | 国产精品k频道 | 日韩高清精品一区二区 | 欧美性大胆 | 久久久久成人精品免费播放动漫 | 午夜少妇av| 97超碰人人澡 | av一级片在线观看 | 欧美日韩在线视频观看 | 亚洲va综合va国产va中文 | 97成人精品视频在线播放 | 中文字幕在线免费观看视频 | 99免费在线视频 | 99精品国产在热久久 | 伊香蕉大综综综合久久啪 | 开心激情婷婷 | 成年美女黄网站色大片免费看 | 天天操综| 日本久久久影视 | 久久公开免费视频 | 日本久久精 | 亚洲精品影视在线观看 | 天天干国产 | 91在线视频免费播放 | 日本久久电影网 | 奇米影视在线99精品 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 色在线亚洲 | 日本在线精品视频 | 国产视频一区二区在线观看 | 久久99久久99精品免观看粉嫩 | 国产无套视频 | 国产一区二区免费看 | 一本一道久久a久久精品蜜桃 | 四虎影视成人精品国库在线观看 | 久热爱| 亚洲另类交 | 9999在线视频| 五月天丁香亚洲 | 国产中文在线视频 | 久久久穴| 91成人精品一区在线播放 | 免费视频国产 | www色婷婷com| 色在线高清 | 欧美日韩国产在线精品 | 中文字幕在线观看资源 | 天天碰天天操视频 | 99久久精品国 | 97精品国产97久久久久久 | 91av在线视频播放 | 国产h在线观看 | 91人人澡人人爽人人精品 | 在线免费观看欧美日韩 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 天天色成人 | 丁香综合激情 | 欧美日韩亚洲第一页 | 成人午夜影院 | 亚洲 成人 欧美 | 国产精品mv在线观看 | 欧美日韩99| a级国产乱理伦片在线观看 亚洲3级 | 人人添人人澡 | 黄色小说18| 亚洲精品男人天堂 | 色综合婷婷久久 | av在线最新 | 国产青草视频在线观看 | 亚洲成人av片 | 国产不卡av在线播放 | 免费男女网站 | 日韩av伦理片 | 国产va饥渴难耐女保洁员在线观看 | 黄色免费观看网址 | 四虎永久网站 | 色婷婷久久久综合中文字幕 | 欧美日韩视频免费 | 黄色成品视频 | 久久久久亚洲精品成人网小说 | 六月天综合网 | 婷婷六月网 | 99爱精品视频 | 一区二区三区免费在线观看视频 | 日韩精品一区不卡 | 中文字幕 影院 | 欧美一区二区三区免费观看 | 丰满少妇一级片 | 一区二区不卡在线观看 | 97涩涩视频 | 国产视频一区二区三区在线 | 久草免费在线视频 | 91在线文字幕 | 欧美日韩免费观看一区二区三区 | 人人澡超碰碰97碰碰碰软件 | 亚洲电影网站 | 欧美极度另类性三渗透 | 国产成人精品一区二区三区福利 | 超碰激情在线 | 久草在线免费电影 | 国产91九色视频 | 香蕉影视app | 国产成人av电影在线 | 国产免费高清 | 日韩av电影免费在线观看 | 日韩电影一区二区在线观看 | 网站你懂的 | 五月婷婷在线视频 | 欧美男男激情videos | 日日爽日日操 | 亚洲精品乱码 | 欧美经典久久 | 国产免码va在线观看免费 | 91av在线视频免费观看 | 一区二区三区韩国免费中文网站 | 日韩一区二区三区不卡 | 91精品无人成人www | 久久久久国产精品一区二区 | 又大又硬又黄又爽视频在线观看 | 中文字幕一区二区三区乱码在线 | 欧美激情精品一区 | 久久久久久国产一区二区三区 | 亚洲成人精品影院 | 国内丰满少妇猛烈精品播 | 九九免费在线观看 | 国产人成精品一区二区三 | av看片网址| 色综合天天爱 | 日韩综合在线观看 | 9999在线观看| 精品久久久久久亚洲综合网站 | 日韩高清精品一区二区 | 五月天免费网站 | 国产精品免费视频观看 | 在线观看视频福利 | 亚洲精品免费在线播放 | 五月婷av | 久草在线免费资源 | 久久亚洲影视 | 一级做a爱片性色毛片www | 欧美一区二视频在线免费观看 | 亚洲三级av| www.夜夜爽| 亚洲国产精品久久久久久 | 免费精品国产va自在自线 | 丝袜美腿在线播放 | 亚洲精品女| 在线岛国av | 久久99久久99精品中文字幕 | 日本在线视频一区二区三区 | 欧美另类交在线观看 | www.777奇米 | 韩国av一区二区 | 国产黄色片在线 | 国产一区影院 | 久久 精品一区 | 欧美a免费 | 欧美日韩不卡一区 | 黄色软件网站在线观看 | 狠狠做六月爱婷婷综合aⅴ 日本高清免费中文字幕 | 干天天| 五月天视频网 | 久久亚洲福利视频 | 黄色av电影 | 成人av在线电影 | 99久在线精品99re8热视频 | 亚洲一二区视频 | 亚洲一区免费在线 | 日韩av一区二区三区四区 | 综合视频在线 | 日本精品一区二区三区在线播放视频 | 午夜精品久久久久久久99婷婷 | 九九视频这里只有精品 | 国产一级黄色片免费看 | 国产手机在线观看 | 91久色蝌蚪 | 国产一区在线免费观看 | 91视频在线免费 | 天天曰天天曰 | 中文资源在线官网 | 国产精品99久久久久久武松影视 | 在线观看亚洲专区 | 992tv又爽又黄的免费视频 | 精品一区二区在线免费观看 | 国产+日韩欧美 | 麻豆va一区二区三区久久浪 | 成人黄色小说网 | 天堂av在线网址 | 欧美激情综合网 | 四虎影视精品 | 九九热在线观看 | 久久乱码卡一卡2卡三卡四 五月婷婷久 | 国产精品九九九九九九 | 久草久草在线观看 | 天堂av在线免费观看 | 91久草视频 | 天天夜夜狠狠操 | 国产精品久久久久永久免费看 | 在线观看亚洲精品视频 | 亚洲欧美精品在线 | 亚洲传媒在线 | 色综合a | 成人精品电影 | 久久综合五月天婷婷伊人 | 国内精品久久久久影院一蜜桃 | 99精品国产一区二区三区不卡 | 欧美午夜视频在线 | 国产精品不卡在线 | 国产免费叼嘿网站免费 | 成人av电影免费在线观看 | 成人久久久久久久久久 | 国产三级视频在线 | 日韩精品一区二区三区丰满 | 在线观看一区视频 | 久久综合九色综合97婷婷女人 | 国产亚洲aⅴaaaaaa毛片 | 欧美日韩国产二区 | 免费一级特黄录像 | 婷婷草 | 久久综合精品一区 | 超碰97免费 | 国产亚洲精品久久久久久 | 伊人黄色网 | 免费网站在线观看人 | 婷婷久久综合九色综合 | 黄色片网站av | 少妇自拍av| 欧美性生活免费 | 亚洲免费成人av电影 | 在线日韩亚洲 | 日韩午夜大片 | 在线免费观看的av | 丁香婷婷在线观看 | 国产视频在线看 | 亚洲精品视频在线播放 | 国产在线精品区 | 久久久久欠精品国产毛片国产毛生 | 国产尤物一区二区三区 | 日韩欧美综合在线视频 | 日韩网页 | 在线观看91久久久久久 | 一区二区三区精品在线视频 | 韩国三级在线一区 | 99爱精品在线 | 久久综合影院 | 欧美视频日韩视频 | 13日本xxxxxⅹxxx20| bbbb操bbbb | 天天色天天艹 | 久久国产亚洲 | 青青河边草免费观看 | 99久久99久久精品国产片果冰 | 91丨精品丨蝌蚪丨白丝jk | 日本特黄一级片 | www.99在线观看 | 天天色欧美 | 在线观看韩日电影免费 | 国产资源免费 | 国产伦精品一区二区三区高清 | 在线视频一区观看 | 九九久久久久99精品 | 国产精品免费看久久久8精臀av | 亚洲欧洲视频 | 欧美激情精品久久久久久免费 | 成人免费一区二区三区在线观看 | 日韩精品久久久久久久电影竹菊 | 一区中文字幕电影 | 国产一级淫片免费看 | 中文字幕在线观看免费高清电影 | 久久午夜国产精品 | 日韩欧美在线视频一区二区三区 | 四虎影视久久久 | 五月婷婷.com | 国产一级h | 狠狠色婷婷丁香六月 | 日日躁夜夜躁aaaaxxxx | 91黄视频在线观看 | 狠狠狠色丁香综合久久天下网 | 婷婷 综合 色 | 久久国产精品久久久 | www国产亚洲 | 免费看一级黄色 | 在线国产激情视频 | 国产福利一区二区三区视频 | 综合网欧美 | 日韩中文字幕免费在线播放 | 亚洲精品综合欧美二区变态 | 亚洲精品视频偷拍 | 国产黄色片免费观看 | 日韩高清片 | 日韩欧美一区二区三区视频 | 丁香五香天综合情 | 日韩av中文在线观看 | 99精品视频在线观看播放 | 日日操狠狠干 | 999久久国精品免费观看网站 | 中文伊人 | 丝袜一区在线 | 国产美女免费观看 | 99人成在线观看视频 | 日韩成人黄色av | 91在线免费观看国产 | 一本一本久久a久久精品牛牛影视 | www免费在线观看 | 99久久这里只有精品 | 亚洲一级影院 | 免费高清无人区完整版 | 五月在线 | 99热这里有| 天天操夜夜干 | 91 在线视频播放 | 久久综合婷婷综合 | 一区二区视频欧美 | 91精品免费| 日韩国产欧美在线视频 | 亚洲国产一区二区精品专区 | 亚洲一级理论片 | 欧美日韩免费一区 | 香蕉视频国产在线观看 | 91麻豆精品国产91久久久更新时间 | 在线观看国产高清视频 | 成人性生交大片免费看中文网站 | 国产色道 | 免费在线日韩 | www.国产在线| 天天草天天 | 国产精品11 | 日本巨乳在线 | 精品国产乱码久久 | 亚洲欧美国产视频 | 欧美成人性网 | 少妇性bbb搡bbb爽爽爽欧美 | 色综合久久66 | 99精品99 | 久久情爱 | 欧美在线观看视频一区二区 | 国产精品久久在线观看 | 国产成人精品国内自产拍免费看 | 999视频在线播放 | 五月婷婷丁香在线观看 | 色中射| 99视频在线精品免费观看2 | 欧美少妇的秘密 | 久久网站最新地址 | 国产成人精品av在线 | 在线观看视频一区二区三区 | 免费在线观看一区二区三区 | 日本在线视频网址 | 精品久久久久久亚洲综合网 | 草莓视频在线观看免费观看 | 天天干天天干天天操 | 日韩高清国产精品 | 日日躁夜夜躁aaaaxxxx | 天无日天天操天天干 | 中文字幕在线播放一区二区 | 色人久久| 日韩va亚洲va欧美va久久 | 中文字幕乱码日本亚洲一区二区 | 毛片精品免费在线观看 | 国产99爱| 91成人免费 | 69亚洲视频 | 精品免费观看视频 | 婷香五月 | 尤物九九久久国产精品的分类 | 亚洲永久精品在线 | 超碰国产在线播放 | 亚洲欧洲在线视频 | 午夜影院一级片 | 久久99亚洲热视 | 国产日韩精品视频 | 青青草国产精品 | 91麻豆文化传媒在线观看 | 国产色婷婷精品综合在线手机播放 | 日韩在线精品一区 | 2022久久国产露脸精品国产 | 狠狠久久伊人 | 国产精品午夜免费福利视频 | 午夜91在线 | 欧美一二三区在线播放 | 成人毛片一区 | 97色se | 亚洲视频在线观看免费 | 国产一级淫片免费看 | 最近更新中文字幕 | 深爱激情婷婷网 | 久久婷婷精品 | 久久视频一区二区 | 久久乱码卡一卡2卡三卡四 五月婷婷久 | 亚州天堂 | 日日干天天插 | 国产91在| 久久国产精品99久久久久久老狼 | 天天躁日日躁狠狠躁 | 久久精品久久久久久久 | 国产精品99精品久久免费 | 日韩首页 | 久久久国产一区二区三区四区小说 | 久久香蕉国产 | 久久久国产一区二区 | 99麻豆久久久国产精品免费 | 国产婷婷精品av在线 | 97精品国产97久久久久久久久久久久 | 国产精品人成电影在线观看 | 91免费国产在线观看 | 亚洲闷骚少妇在线观看网站 | 精品91视频 | 午夜国产一区二区 | 婷婷综合亚洲 | 亚洲国产视频网站 | 91视频三区 | 国产永久免费高清在线观看视频 | 天天做日日爱夜夜爽 | 丁香六月天 | 久草在线资源网 | 在线观看国产麻豆 | 中文字幕国产精品一区二区 | 日韩欧美一区二区三区在线观看 | av在线超碰 | 九九综合九九综合 | 激情综合五月 | 九九视频这里只有精品 | 国产精品视频内 | 欧美日韩综合在线 | 伊人久久五月天 | av三级在线播放 | 韩国三级一区 | 在线导航av| 久久夜夜爽 | 婷婷在线视频 | 国产黑丝一区二区 | 一区二区三区日韩精品 | 久久99久久99精品免费看小说 | 久久精品日韩 | 日韩字幕 | 一级黄色片在线 | 久久激情婷婷 | 精品久久久久久国产 | 婷婷激情久久 | 成人毛片在线视频 | 99视频偷窥在线精品国自产拍 | 日韩精品1区2区 | 国产精品久久久久久久久久东京 | 亚洲成人av一区二区 | 特级大胆西西4444www | 五月精品 | 精品一区精品二区高清 | 国产录像在线观看 | japanesefreesex中国少妇 | 成人91av| 欧美性生交大片免网 | 久在线观看视频 | 久久不射影院 | 99热99热| 中文字幕在线观看三区 | 中文字幕黄色网址 | 久久综合中文色婷婷 | 免费高清在线视频一区· | 在线观看日韩精品视频 | 亚洲涩涩色 | 综合久久久久久久久 | 日日操网 | 亚洲激情中文 | 五月激情片 | 久久久精品免费看 | 久久免费美女视频 | 亚洲午夜久久久影院 | 激情婷婷丁香 | 97人人澡人人爽人人模亚洲 | 欧美日韩免费一区二区三区 | 婷婷草| 久草在线视频免费资源观看 | 日日弄天天弄美女bbbb | 国产成人精品网站 | 日韩欧美在线第一页 | 国产精品免费观看网站 | 又黄又爽免费视频 | 免费看污网站 | 国产一区在线视频观看 | 9797在线看片亚洲精品 | 一区在线观看视频 | 91精品国产91久久久久福利 | 欧美视屏一区二区 | 天天插日日插 | 日本系列中文字幕 | www日韩视频 | av网站免费线看精品 | 国产午夜精品一区二区三区欧美 | 欧美日韩一级视频 | 99麻豆久久久国产精品免费 | 中文视频一区二区 | 亚洲女人天堂成人av在线 | 91尤物国产尤物福利在线播放 | 国产黄色免费电影 | 嫩草av在线| 国产一区二区免费 | 99九九免费视频 | 日韩精品久久久久久久电影99爱 | 免费a v视频 | 日韩理论电影在线观看 | 成人综合日日夜夜 | 亚洲一级片 | 久草免费在线视频 | 欧洲性视频 | 中文字幕一区二区三区在线播放 | 在线观看亚洲成人 | 在线国产中文字幕 | 国产精品99久久久久久有的能看 | 91九色自拍 | 中文字幕中文字幕在线中文字幕三区 | 国产在线毛片 | 碰超在线观看 | 国产成人精品女人久久久 | 亚洲一级理论片 | 成人在线播放网站 | 日本精品一区二区在线观看 | 天堂av在线免费观看 | 国产在线黄 | 中文字幕在线观看亚洲 | 成人性生交大片免费看中文网站 | 狠狠色丁香 | 嫩草伊人久久精品少妇av | 成人av中文字幕在线观看 | 91在线你懂的 | 亚洲国产精品999 | 亚洲综合网| av电影免费看 | 国产精品美女久久久久久网站 | 亚洲高清在线观看视频 | 久久99国产一区二区三区 | 成人一级在线观看 | 亚洲专区中文字幕 | av成人动漫| 在线免费观看视频你懂的 | av中文字幕不卡 | 日韩高清一二区 | 天天操天天舔天天爽 | 色婷五月天 | 黄色av播放 | 91看片在线观看 | 免费一级片在线观看 | 激情综合色综合久久综合 | 激情久久久久久久久久久久久久久久 | 亚洲欧美日韩在线一区二区 | 亚洲欧美日韩一二三区 | 亚洲精品在线播放视频 | 99热都是精品 | 天天色综合1 | 国产精品岛国久久久久久久久红粉 | 狠狠躁夜夜躁人人爽超碰91 | 国产h片在线观看 | 99中文字幕视频 | 视频91在线 | 波多野结衣久久资源 | va视频在线观看 | 国产成本人视频在线观看 | 三级在线播放视频 | av在线专区 | 不卡电影一区二区三区 | 国产97av| 成片人卡1卡2卡3手机免费看 | 国产精品成人品 | 欧美老人xxxx18| 中文字幕久久精品亚洲乱码 | 国产精品96久久久久久吹潮 | 香蕉视频在线视频 | 免费福利在线观看 | 免费在线黄色av | 国产成人精品av在线 | 国产黄网站在线观看 | 丁香婷婷综合激情五月色 | 欧美性黑人 | 婷婷网站天天婷婷网站 | 超碰在线公开免费 | 久久久久国产精品一区 | 不卡av电影在线观看 | 69av免费视频 | 亚洲精品乱码久久久久v最新版 | 亚洲国产综合在线 | 欧美另类网站 | 一区二区三区精品久久久 | 久久国产露脸精品国产 | 国产做爰视频 | www.操.com | 在线视频一区二区 | 国内三级在线观看 | 在线欧美小视频 | 国产综合精品一区二区三区 | 深爱开心激情 | 免费在线电影网址大全 | 日韩久久久久久久 | 九九综合久久 | 一区二区三区 中文字幕 | 国产高清免费观看 | 欧美天堂久久 | 久久久精品国产一区二区电影四季 | 人人要人人澡人人爽人人dvd | 伊人色综合久久天天网 | 成人片在线播放 | av资源在线看 | 在线观看日韩中文字幕 | 成年人网站免费在线观看 | 欧美 国产 视频 | 免费在线观看的av网站 | 五月天综合激情网 | 91亚洲精品视频 | 在线 欧美 日韩 | 国产三级香港三韩国三级 | av在线永久免费观看 | 日本在线观看中文字幕无线观看 | 久久国产精品第一页 | 天天草天天 | 亚洲无人区小视频 | 欧美国产91 | 91九色精品女同系列 | 黄色不卡av| www在线观看视频 | 91精品一区二区三区蜜臀 | 国产国语在线 | 欧美精品视 | 亚洲人成人天堂h久久 | 五月婷婷在线综合 | 亚洲精品视频在线观看免费视频 | 在线激情电影 | 五月精品 | 精品国产电影一区二区 | 狠狠操精品 | av在线亚洲天堂 | 天天干天天摸天天操 | 国产在线观看免 | 九色91在线 | 久久黄色影院 | 国产91免费在线观看 | 日韩精品在线视频免费观看 | 日韩视频区 | 女人18毛片a级毛片一区二区 | 免费视频久久久 | 日本夜夜草视频网站 | 中文字幕 91 | www国产一区 | 国产中文字幕一区二区 | av在线影视| 500部大龄熟乱视频使用方法 | a在线视频v视频 | 国产在线一区观看 | 久久久久久久久久久免费av | 奇米777777| 国产录像在线观看 |