久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

浅谈Unity中的优化

發(fā)布時(shí)間:2023/12/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈Unity中的优化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 0-前言
    • 1-GC介紹
      • 1.1-腦圖
      • 1.1-介紹
      • 1.2-Unity內(nèi)存管理機(jī)制簡(jiǎn)介
      • 1.3-棧內(nèi)存分配和回收機(jī)制
      • 1.4-堆內(nèi)存分配和回收機(jī)制
      • 1.5-垃圾回收時(shí)的操作
      • 1.6-何時(shí)會(huì)觸發(fā)垃圾回收
      • 1.7-GC操作帶來的問題
    • 2-GC分析及優(yōu)化
      • 2.1-分析GC帶來的問題
      • 2.2-分析堆內(nèi)存的分配
        • 2.2.1-堆內(nèi)存和堆棧內(nèi)存分配的變量類型
        • 2.2.2-利用profiler window 來檢測(cè)堆內(nèi)存分配
      • 2.3-降低GC的影響的方法
      • 2.4-減少內(nèi)存垃圾的數(shù)量
        • 2.4.1-緩存
        • 2.4.2-不要在頻繁調(diào)用的函數(shù)中反復(fù)進(jìn)行堆內(nèi)存分配
        • 2.4.3-清除鏈表
        • 2.4.4-對(duì)象池
      • 2.5-造成不必要的堆內(nèi)存分配的因素
        • 2.5.1-字符串
        • 2.5.2-Unity函數(shù)調(diào)用
        • 2.5.3-裝箱操作
        • 2.5.4-協(xié)程
        • 2.5.5-函數(shù)引用
        • 2.5.6-LINQ和常量表達(dá)式
      • 2.6-重構(gòu)代碼來減小GC的影響
      • 2.7-定時(shí)執(zhí)行GC操作
        • 2.7.1-主動(dòng)調(diào)用GC操作
    • 3-解讀Unity性能優(yōu)化
      • 3.1-常見的Unity性能問題
      • 3.2-Unity運(yùn)行時(shí)的內(nèi)存占用情況
      • 3.3-內(nèi)存標(biāo)準(zhǔn)
      • 3.4-Mono內(nèi)存管理策略
      • 3.5-Mono內(nèi)存泄漏分析
      • 3.6-優(yōu)化
        • 3.6.1-DrawCall優(yōu)化
        • 3.6.2-CPU優(yōu)化最直接的方法
        • 3.6.3-GPU優(yōu)化
      • 3.7-研發(fā)團(tuán)隊(duì)需要關(guān)注的引擎模塊
      • 3.8-開始優(yōu)化工作
    • 4-Unity3D性能優(yōu)化——初識(shí)Unity-Statistics
    • 5-Unity3D性能優(yōu)化——Unity篇
      • 5.1-Unity 腳本開發(fā)方面
      • 5.2-Unity資源相關(guān)優(yōu)化
        • 5.2.1-音頻
        • 5.2.2-Texture
        • 5.2.3-模型
        • 5.2.4-文本文件優(yōu)化
        • 5.2.5-AssetBundle管理
        • 5.2.6-資源工作流管理
      • 5.3-Unity相機(jī)優(yōu)化
        • 5.3.1-Occlusion Culling遮擋剔除
        • 5.3.2-Frustum Culling視錐體剔除
      • 5.4-UnityUGUI優(yōu)化
      • 5.5-C# 語言層面的優(yōu)化
      • 5.6-圖形渲染層面
    • 6-Unity3D性能優(yōu)化——工具篇
      • 6.1-游戲性能簡(jiǎn)述
      • 6.2-Unity3d性能分析工具
        • 6.2.1-Unity Profile
        • 6.2.2-其他性能分析工具

0-前言

此文章為網(wǎng)上轉(zhuǎn)載收集而成,非原創(chuàng)文章,請(qǐng)尊重別人的勞動(dòng)成果,讓分享成為一種美德,歡迎轉(zhuǎn)載。另外,文章在表述和代碼方面如有不妥之處,歡迎批評(píng)指正。同時(shí)大家有更好的優(yōu)化方案,或者自己獨(dú)立見解的優(yōu)化想法,也請(qǐng)發(fā)相關(guān)郵件于我,我將持續(xù)更新這篇文章,努力將“淺談”轉(zhuǎn)變?yōu)椤吧钊搿?#xff01;
觀前提示:本文篇幅較長(zhǎng),請(qǐng)耐心觀看或收藏

本文鏈接https://blog.csdn.net/qq_23420435/article/details/110109812

當(dāng)前版本:V0.0.0 更新時(shí)間:2020-11-25 更新內(nèi)容:首次整合更新 更新管理:小小Editor

收集整合

18328685848@163.com----轉(zhuǎn)載收集整合 小小Editor

章節(jié)一《CG介紹》、章節(jié)二《GC分析及優(yōu)化》

http://www.cnblogs.com/msxh/p/6531725.html https://blog.csdn.net/worisaa/article/details/64121436----原創(chuàng) 路人張德帥----轉(zhuǎn)載 worisaa

章節(jié)三《解讀Unity性能優(yōu)化》

https://www.jianshu.com/p/e427a38e91c3----Jumbo

章節(jié)四《Unity3D性能優(yōu)化——初識(shí)Unity-Statistics》

https://blog.csdn.net/wdmzjzlym/article/details/51335915----萌萌的一天

章節(jié)五《Unity3D性能優(yōu)化——Unity篇》

https://blog.csdn.net/weixin_43967425/article/details/84928476----原創(chuàng) Kyle_GISer----原創(chuàng) 網(wǎng)絡(luò)

章節(jié)五點(diǎn)二《5.2-Unity資源相關(guān)優(yōu)化》

https://blog.csdn.net/u012565990/article/details/51794486 https://blog.csdn.net/u013709166/article/details/54959464?----原創(chuàng) CZandQZ----原創(chuàng) ResetOTER

章節(jié)五點(diǎn)三點(diǎn)一《Occlusion Culling遮擋剔除

https://blog.csdn.net/qq_37672438/article/details/100933982----原創(chuàng) 路人張德帥

章節(jié)五點(diǎn)三點(diǎn)二《Frustum Culling視錐體剔除》

https://blog.csdn.net/xinjay1992/article/details/107550433?----原創(chuàng) 程序員茶館

章節(jié)五點(diǎn)四《5.4-UnityUGUI優(yōu)化》

https://mp.weixin.qq.com/s?__biz=MzU5MjQ1NTEwOA==&mid=2247495094&idx=1&sn= 4a948884855c5a6f26f73ff7845c8caf&chksm=fe1dd91dc96a500baf2970fed3b13009e89 7997472f6596325102dff0cad616defd7a2470d52&token=2019102974&lang=zh_CN#rd----原創(chuàng) Unity官方平臺(tái)----原創(chuàng) 網(wǎng)絡(luò)

章節(jié)六《Unity3D性能優(yōu)化——工具篇》

https://zhuanlan.zhihu.com/p/39529241----朔宇

1-GC介紹

1.1-腦圖

1.1-介紹

在游戲運(yùn)行的時(shí)候,數(shù)據(jù)主要存儲(chǔ)在內(nèi)存中,當(dāng)游戲的數(shù)據(jù)不在需要的時(shí)候,存儲(chǔ)當(dāng)前數(shù)據(jù)的內(nèi)存就可以被回收再次使用。內(nèi)存垃圾是指當(dāng)前廢棄數(shù)據(jù)所占用的內(nèi)存,垃圾回收(GC)是指將廢棄的內(nèi)存重新回收再次使用的過程。

Unity中將垃圾回收當(dāng)作內(nèi)存管理的一部分,如果游戲中垃圾回收十分復(fù)雜,則游戲的性能會(huì)受到極大影響,此時(shí)垃圾回收會(huì)成為游戲性能的一大障礙點(diǎn)。

下面我們將會(huì)學(xué)習(xí)垃圾回收的機(jī)制,掌握垃圾回收如何被觸發(fā)以及如何提高垃圾回收效率來減小其對(duì)游戲行性能的影響。

1.2-Unity內(nèi)存管理機(jī)制簡(jiǎn)介

要想了解垃圾回收如何工作以及何時(shí)被觸發(fā),我們首先需要了解unity的內(nèi)存管理機(jī)制。Unity主要采用自動(dòng)內(nèi)存管理的機(jī)制,開發(fā)時(shí)在代碼中不需要詳細(xì)地告訴unity如何進(jìn)行內(nèi)存管理,unity內(nèi)部自身會(huì)進(jìn)行內(nèi)存管理。

unity的自動(dòng)內(nèi)存管理可以理解為以下幾個(gè)部分:

  • unity內(nèi)部有兩個(gè)內(nèi)存管理池:堆內(nèi)存和堆棧內(nèi)存。堆棧內(nèi)存(stack)主要用來存儲(chǔ)較小的和短暫的數(shù)據(jù)片段,堆內(nèi)存(heap)主要用來存儲(chǔ)較大的和存儲(chǔ)時(shí)間較長(zhǎng)的數(shù)據(jù)片段。
  • unity中的變量只會(huì)在堆?;蛘叨褍?nèi)存上進(jìn)行內(nèi)存分配。
  • 只要變量處于激活狀態(tài),則其占用的內(nèi)存會(huì)被標(biāo)記為使用狀態(tài),則該部分的內(nèi)存處于被分配的狀態(tài),變量要么存儲(chǔ)在堆棧內(nèi)存上,要么處于堆內(nèi)存上。
  • 一旦變量不再激活,則其所占用的內(nèi)存不再需要,該部分內(nèi)存可以被回收到內(nèi)存池中被再次使用,這樣的操作就是內(nèi)存回收。處于堆棧上的內(nèi)存回收及其快速,處于堆上的內(nèi)存并不是及時(shí)回收的,其對(duì)應(yīng)的內(nèi)存依然會(huì)被標(biāo)記為使用狀態(tài)。
  • 垃圾回收主要是指堆上的內(nèi)存分配和回收,unity中會(huì)定時(shí)對(duì)堆內(nèi)存進(jìn)行GC操作。

在了解了GC的過程后,下面詳細(xì)了解堆內(nèi)存和堆棧內(nèi)存的分配和回收機(jī)制的差別。

1.3-棧內(nèi)存分配和回收機(jī)制

棧上的內(nèi)存分配和回收十分快捷簡(jiǎn)單,主要是棧上只會(huì)存儲(chǔ)短暫的較小的變量。內(nèi)存分配和回收都會(huì)以一種可控制順序和大小的方式進(jìn)行。

棧的運(yùn)行方式就像 stack :只是一個(gè)數(shù)據(jù)的集合,數(shù)據(jù)的進(jìn)出都以一種固定的方式運(yùn)行。正是這種簡(jiǎn)潔性和固定性使得堆棧的操作十分快捷。當(dāng)數(shù)據(jù)被存儲(chǔ)在棧上的時(shí)候,只需要簡(jiǎn)單地在其后進(jìn)行擴(kuò)展。當(dāng)數(shù)據(jù)失效的時(shí)候,只需要將其從棧上移除復(fù)用。

1.4-堆內(nèi)存分配和回收機(jī)制

堆內(nèi)存上的內(nèi)存分配和存儲(chǔ)相對(duì)而言更加復(fù)雜,主要是堆內(nèi)存上可以存儲(chǔ)短期較小的數(shù)據(jù),也可以存儲(chǔ)各種類型和大小的數(shù)據(jù)。其上的內(nèi)存分配和回收順序并不可控,可能會(huì)要求分配不同大小的內(nèi)存單元來存儲(chǔ)數(shù)據(jù)。

堆上的變量在存儲(chǔ)的時(shí)候,主要分為以下幾步:

  • 首先,unity檢測(cè)是否有足夠的閑置內(nèi)存單元用來存儲(chǔ)數(shù)據(jù),如果有,則分配對(duì)應(yīng)的內(nèi)存單元;
  • 如果沒有足夠的存儲(chǔ)單元,unity會(huì)觸發(fā)垃圾回收來釋放不再被使用的堆內(nèi)存。這步操作是一步緩慢的操作,如果垃圾回收后有足夠的內(nèi)存單元,則進(jìn)行內(nèi)存分配。
  • 如果垃圾回收后并沒有足夠的內(nèi)存單元,則unity會(huì)擴(kuò)展堆內(nèi)存的大小,這步操作會(huì)很緩慢,然后分配對(duì)應(yīng)的內(nèi)存單元給變量。

堆內(nèi)存的分配有可能會(huì)變得十分緩慢,特別是需要垃圾回收和堆內(nèi)存需要擴(kuò)展的情況下。

1.5-垃圾回收時(shí)的操作

當(dāng)一個(gè)變量不再處于激活狀態(tài)的時(shí)候,其所占用的內(nèi)存并不會(huì)立刻被回收,不再使用的內(nèi)存只會(huì)在GC的時(shí)候才會(huì)被回收。

每次運(yùn)行GC的時(shí)候,主要進(jìn)行下面的操作:

  • GC會(huì)檢查堆內(nèi)存上的每個(gè)存儲(chǔ)變量;
  • 對(duì)每個(gè)變量會(huì)檢測(cè)其引用是否處于激活狀態(tài);
  • 如果變量的引用不再處于激活狀態(tài),則會(huì)被標(biāo)記為可回收;
  • 被標(biāo)記的變量會(huì)被移除,其所占有的內(nèi)存會(huì)被回收到堆內(nèi)存上。

GC操作是一個(gè)極其耗費(fèi)的操作,堆內(nèi)存上的變量或者引用越多則其運(yùn)行的操作會(huì)更多,耗費(fèi)的時(shí)間越長(zhǎng)。

1.6-何時(shí)會(huì)觸發(fā)垃圾回收

主要有三個(gè)操作會(huì)觸發(fā)垃圾回收:

  • 在堆內(nèi)存上進(jìn)行內(nèi)存分配操作而內(nèi)存不夠的時(shí)候都會(huì)觸發(fā)垃圾回收來利用閑置的內(nèi)存;
  • GC會(huì)自動(dòng)的觸發(fā),不同平臺(tái)運(yùn)行頻率不一樣;
  • GC可以被強(qiáng)制執(zhí)行。

GC操作可以被頻繁觸發(fā),特別是在堆內(nèi)存上進(jìn)行內(nèi)存分配時(shí)內(nèi)存單元不足夠的時(shí)候,這就意味著頻繁在堆內(nèi)存上進(jìn)行內(nèi)存分配和回收會(huì)觸發(fā)頻繁的GC操作。

1.7-GC操作帶來的問題

在了解GC在unity內(nèi)存管理中的作用后,我們需要考慮其帶來的問題。最明顯的問題是GC操作會(huì)需要大量的時(shí)間來運(yùn)行,如果堆內(nèi)存上有大量的變量或者引用需要檢查,則檢查的操作會(huì)十分緩慢,這就會(huì)使得游戲運(yùn)行緩慢。其次GC可能會(huì)在關(guān)鍵時(shí)候運(yùn)行,例如CPU處于游戲的性能運(yùn)行關(guān)鍵時(shí)刻,其他的任何一個(gè)額外的操作都可能會(huì)帶來極大的影響,使得游戲幀率下降。

另外一個(gè)GC帶來的問題是堆內(nèi)存碎片。當(dāng)一個(gè)內(nèi)存單元從堆內(nèi)存上分配出來,其大小取決于其存儲(chǔ)的變量的大小。當(dāng)該內(nèi)存被回收到堆內(nèi)存上的時(shí)候,有可能使得堆內(nèi)存被分割成碎片化的單元。也就是說堆內(nèi)存總體可以使用的內(nèi)存單元較大,但是單獨(dú)的內(nèi)存單元較小,在下次內(nèi)存分配的時(shí)候不能找到合適大小的存儲(chǔ)單元,這就會(huì)觸發(fā)GC操作或者堆內(nèi)存擴(kuò)展操作。

堆內(nèi)存碎片會(huì)造成兩個(gè)結(jié)果,一個(gè)是游戲占用的內(nèi)存會(huì)越來越大,一個(gè)是GC會(huì)更加頻繁地被觸發(fā)。

2-GC分析及優(yōu)化

2.1-分析GC帶來的問題

GC操作帶來的問題主要表現(xiàn)為幀率運(yùn)行低,性能間歇中斷或者降低。如果游戲有這樣的表現(xiàn),則首先需要打開unity中的profiler window來確定是否是GC造成。

了解如何運(yùn)用profiler window,可以參考此處,如果游戲確實(shí)是由GC造成的,可以繼續(xù)閱讀下面的內(nèi)容。

2.2-分析堆內(nèi)存的分配

如果GC造成游戲的性能問題,我們需要知道游戲中的哪部分代碼會(huì)造成GC,內(nèi)存垃圾在變量不再激活的時(shí)候產(chǎn)生,所以首先我們需要知道堆內(nèi)存上分配的是什么變量。

2.2.1-堆內(nèi)存和堆棧內(nèi)存分配的變量類型

在Unity中,值類型變量都在堆棧上進(jìn)行內(nèi)存分配,其他類型的變量都在堆內(nèi)存上分配。如果你不知道值類型和引用類型的差別,可以查看此處。

下面的代碼可以用來理解值類型的分配和釋放,其對(duì)應(yīng)的變量在函數(shù)調(diào)用完后會(huì)立即回收:

下面的代碼可以用來理解值類型的分配和釋放,其對(duì)應(yīng)的變量在函數(shù)調(diào)用完后會(huì)立即回收:

void ExampleFunciton() {int localInt = 5; }

對(duì)應(yīng)的引用類型的參考代碼如下,其對(duì)應(yīng)的變量在GC的時(shí)候才回收:

void ExampleFunction() {List localList = new List(); }

2.2.2-利用profiler window 來檢測(cè)堆內(nèi)存分配

我們可以在profier window中檢查堆內(nèi)存的分配操作:在CPU usage分析窗口中,我們可以檢測(cè)任何一幀cpu的內(nèi)存分配情況。其中一個(gè)選項(xiàng)是GC alloc,通過分析其來定位是什么函數(shù)造成大量的堆內(nèi)存分配操作。一旦定位該函數(shù),我們就可以分析解決其造成問題的原因從而減少內(nèi)存垃圾的產(chǎn)生。

2.3-降低GC的影響的方法

大體上來說,我們可以通過三種方法來降低GC的影響:

  • 減少GC的運(yùn)行次數(shù);
  • 減少單次GC的運(yùn)行時(shí)間;
  • 將GC的運(yùn)行時(shí)間延遲,避免在關(guān)鍵時(shí)候觸發(fā),比如可以在場(chǎng)景加載的時(shí)候調(diào)用GC

基于此,我們可以采用三種策略:

  • 對(duì)游戲進(jìn)行重構(gòu),減少堆內(nèi)存的分配和引用的分配。更少的變量和引用會(huì)減少GC操作中的檢測(cè)個(gè)數(shù)從而提高GC的運(yùn)行效率。
  • 降低堆內(nèi)存分配和回收的頻率,尤其是在關(guān)鍵時(shí)刻。也就是說更少的事件觸發(fā)GC操作,同時(shí)也降低堆內(nèi)存碎片。
  • 我們可以試著測(cè)量GC和堆內(nèi)存擴(kuò)展的時(shí)間,使其按照可預(yù)測(cè)的順序執(zhí)行。當(dāng)然這樣操作的難度極大,但是這會(huì)大大降低GC的影響。

2.4-減少內(nèi)存垃圾的數(shù)量

減少內(nèi)存垃圾主要可以通過一些方法來減少:

2.4.1-緩存

如果在代碼中反復(fù)調(diào)用某些造成堆內(nèi)存分配的函數(shù)但是其返回結(jié)果并沒有使用,這就會(huì)造成不必要的內(nèi)存垃圾,我們可以緩存這些變量來重復(fù)利用,這就是緩存。

例如下面的代碼每次調(diào)用的時(shí)候就會(huì)造成堆內(nèi)存分配,主要是每次都會(huì)分配一個(gè)新的數(shù)組:

void OnTriggerEnter(Collider other) {Renderer[] allRenderers = FindObjectsOfType<Renderer>();ExampleFunction(allRenderers); }

對(duì)比下面的代碼,只會(huì)生產(chǎn)一個(gè)數(shù)組用來緩存數(shù)據(jù),實(shí)現(xiàn)反復(fù)利用而不需要造成更多的內(nèi)存垃圾:

private Renderer[] allRenderers;void Start() {allRenderers = FindObjectsOfType<Renderer>(); }void OnTriggerEnter(Collider other) {ExampleFunction(allRenderers); }

2.4.2-不要在頻繁調(diào)用的函數(shù)中反復(fù)進(jìn)行堆內(nèi)存分配

在MonoBehaviour中,如果我們需要進(jìn)行堆內(nèi)存分配,最壞的情況就是在其反復(fù)調(diào)用的函數(shù)中進(jìn)行堆內(nèi)存分配,例如Update()和LateUpdate()函數(shù)這種每幀都調(diào)用的函數(shù),這會(huì)造成大量的內(nèi)存垃圾。我們可以考慮在Start()或者Awake()函數(shù)中進(jìn)行內(nèi)存分配,這樣可以減少內(nèi)存垃圾。

下面的例子中,update函數(shù)會(huì)多次觸發(fā)內(nèi)存垃圾的產(chǎn)生:

void Update() {ExampleGarbageGenerationFunction(transform.position.x); }

通過一個(gè)簡(jiǎn)單的改變,我們可以確保每次在x改變的時(shí)候才觸發(fā)函數(shù)調(diào)用,這樣避免每幀都進(jìn)行堆內(nèi)存分配:

private float previousTransformPositionX;void Update() {float transformPositionX = transform.position.x;if(transfromPositionX != previousTransformPositionX){ExampleGarbageGenerationFunction(transformPositionX); previousTransformPositionX = trasnformPositionX;} }

另外的一種方法是在update中采用計(jì)時(shí)器,特別是在運(yùn)行有規(guī)律但是不需要每幀都運(yùn)行的代碼中,例如:

void Update() {ExampleGarbageGeneratiingFunction() }

通過添加一個(gè)計(jì)時(shí)器,我們可以確保每隔1s才觸發(fā)該函數(shù)一次:

private float timeSinceLastCalled; private float delay = 1f; void Update() {timSinceLastCalled += Time.deltaTime;if(timeSinceLastCalled > delay){ExampleGarbageGenerationFunction();timeSinceLastCalled = 0f;} }

通過這樣細(xì)小的改變,我們可以使得代碼運(yùn)行的更快同時(shí)減少內(nèi)存垃圾的產(chǎn)生。

2.4.3-清除鏈表

在堆內(nèi)存上進(jìn)行鏈表的分配的時(shí)候,如果該鏈表需要多次反復(fù)的分配,我們可以采用鏈表的clear函數(shù)來清空鏈表從而替代反復(fù)多次的創(chuàng)建分配鏈表。

void Update() {List myList = new List();PopulateList(myList); }

通過改進(jìn),我們可以將該鏈表只在第一次創(chuàng)建或者該鏈表必須重新設(shè)置的時(shí)候才進(jìn)行堆內(nèi)存分配,從而大大減少內(nèi)存垃圾的產(chǎn)生:

private List myList = new List(); void Update() {myList.Clear();PopulateList(myList); }

2.4.4-對(duì)象池

即便我們?cè)诖a中盡可能地減少堆內(nèi)存的分配行為,但是如果游戲有大量的對(duì)象需要產(chǎn)生和銷毀依然會(huì)造成GC。對(duì)象池技術(shù)可以通過重復(fù)使用objects來降低堆內(nèi)存的分配和回收頻率。對(duì)象池在游戲中廣泛的使用,特別是在游戲中需要頻繁的創(chuàng)建和銷毀相同的游戲?qū)ο蟮臅r(shí)候,例如槍的子彈。

要詳細(xì)的講解對(duì)象池已經(jīng)超出本文的范圍,但是該技術(shù)值得我們深入的研究This tutorial on object pooling on the Unity Learn site對(duì)于對(duì)象池有詳細(xì)深入的講解。

2.5-造成不必要的堆內(nèi)存分配的因素

我們已經(jīng)知道值類型變量在堆棧上分配,其他的變量在堆內(nèi)存上分配,但是任然有一些情況下的堆內(nèi)存分配會(huì)讓我們感到吃驚。下面讓我們分析一些常見的不必要的堆內(nèi)存分配行為并對(duì)其進(jìn)行優(yōu)化。

2.5.1-字符串

在c#中,字符串是引用類型變量而不是值類型變量,即使看起來它是存儲(chǔ)字符串的值的。這就意味著字符串會(huì)造成一定的內(nèi)存垃圾,由于代碼中經(jīng)常使用字符串,所以我們需要對(duì)其格外小心。

c#中的字符串是不可變更的,也就是說其內(nèi)部的值在創(chuàng)建后是不可被變更的。每次在對(duì)字符串進(jìn)行操作的時(shí)候(例如運(yùn)用字符串的“加”操作),unity會(huì)新建一個(gè)字符串用來存儲(chǔ)新的字符串,使得舊的字符串被廢棄,這樣就會(huì)造成內(nèi)存垃圾。

我們可以采用以下的一些方法來最小化字符串的影響:

1)減少不必要的字符串的創(chuàng)建,如果一個(gè)字符串被多次利用,我們可以創(chuàng)建并緩存該字符串。

2)減少不必要的字符串操作,例如如果在Text組件中,有一部分字符串需要經(jīng)常改變,但是其他部分不會(huì),則我們可以將其分為兩個(gè)部分的組件。

3)如果我們需要實(shí)時(shí)的創(chuàng)建字符串,我們可以采用StringBuilderClass來代替,StringBuilder專為不需要進(jìn)行內(nèi)存分配而設(shè)計(jì),從而減少字符串產(chǎn)生的內(nèi)存垃圾。

4)移除游戲中的Debug.Log()函數(shù)的代碼,盡管該函數(shù)可能輸出為空,對(duì)該函數(shù)的調(diào)用依然會(huì)執(zhí)行,該函數(shù)會(huì)創(chuàng)建至少一個(gè)字符(空字符)的字符串。如果游戲中有大量的該函數(shù)的調(diào)用,這會(huì)造成內(nèi)存垃圾的增加。

在下面的代碼中,在Update函數(shù)中會(huì)進(jìn)行一個(gè)string的操作,這樣的操作就會(huì)造成不必要的內(nèi)存垃圾:

public Text timerText; private float timer; void Update() {timer += Time.deltaTime;timerText.text = "Time:"+ timer.ToString(); }

通過將字符串進(jìn)行分隔,我們可以剔除字符串的加操作,從而減少不必要的內(nèi)存垃圾:

public Text timerHeaderText; public Text timerValueText; private float timer; void Start() {timerHeaderText.text = "TIME:"; }void Update() {timerValueText.text = timer.ToString(); }

2.5.2-Unity函數(shù)調(diào)用

在代碼編程中,我們需要知道當(dāng)我們調(diào)用不是我們自己編寫的代碼,無論是Unity自帶的還是插件中的,我們都可能會(huì)產(chǎn)生內(nèi)存垃圾。Unity的某些函數(shù)調(diào)用會(huì)產(chǎn)生內(nèi)存垃圾,我們?cè)谑褂玫臅r(shí)候需要注意它的使用。

這兒沒有明確的列表指出哪些函數(shù)需要注意,每個(gè)函數(shù)在不同的情況下有不同的使用,所以最好仔細(xì)地分析游戲,定位內(nèi)存垃圾的產(chǎn)生原因以及如何解決問題。有時(shí)候緩存是一種有效的辦法,有時(shí)候盡量降低函數(shù)的調(diào)用頻率是一種辦法,有時(shí)候用其他函數(shù)來重構(gòu)代碼是一種辦法。現(xiàn)在來分析unity中中常見的造成堆內(nèi)存分配的函數(shù)調(diào)用。

在Unity中如果函數(shù)需要返回一個(gè)數(shù)組,則一個(gè)新的數(shù)組會(huì)被分配出來用作結(jié)果返回,這不容易被注意到,特別是如果該函數(shù)含有迭代器,下面的代碼中對(duì)于每個(gè)迭代器都會(huì)產(chǎn)生一個(gè)新的數(shù)組:

void ExampleFunction() {for(int i=0; i < myMesh.normals.Length;i++){Vector3 normal = myMesh.normals[i];} }

對(duì)于這樣的問題,我們可以緩存一個(gè)數(shù)組的引用,這樣只需要分配一個(gè)數(shù)組就可以實(shí)現(xiàn)相同的功能,從而減少內(nèi)存垃圾的產(chǎn)生:

void ExampleFunction() {Vector3[] meshNormals = myMesh.normals;for(int i=0; i < meshNormals.Length;i++){Vector3 normal = meshNormals[i];} }

此外另外的一個(gè)函數(shù)調(diào)用GameObject.name 或者 GameObject.tag也會(huì)造成預(yù)想不到的堆內(nèi)存分配,這兩個(gè)函數(shù)都會(huì)將結(jié)果存為新的字符串返回,這就會(huì)造成不必要的內(nèi)存垃圾,對(duì)結(jié)果進(jìn)行緩存是一種有效的辦法,但是在Unity中都對(duì)應(yīng)的有相關(guān)的函數(shù)來替代。對(duì)于比較gameObject的tag,可以采用GameObject.CompareTag()來替代。

在下面的代碼中,調(diào)用gameobject.tag就會(huì)產(chǎn)生內(nèi)存垃圾:

private string playerTag="Player"; void OnTriggerEnter(Collider other) {bool isPlayer = other.gameObject.tag ==playerTag; }

采用GameObject.CompareTag()可以避免內(nèi)存垃圾的產(chǎn)生:

private string playerTag = "Player"; void OnTriggerEnter(Collider other) {bool isPlayer = other.gameObject.CompareTag(playerTag); }

不只是GameObject.CompareTag,unity中許多其他的函數(shù)也可以避免內(nèi)存垃圾的生成。比如我們可以用Input.GetTouch()和Input.touchCount()來代替Input.touches,或者用Physics.SphereCastNonAlloc()來代替Physics.SphereCastAll()。

2.5.3-裝箱操作

裝箱操作是指一個(gè)值類型變量被用作引用類型變量時(shí)候的內(nèi)部變換過程,如果我們向帶有對(duì)象類型參數(shù)的函數(shù)傳入值類型,這就會(huì)觸發(fā)裝箱操作。比如String.Format()函數(shù)需要傳入字符串和對(duì)象類型參數(shù),如果傳入字符串和int類型數(shù)據(jù),就會(huì)觸發(fā)裝箱操作。如下面代碼所示:

void ExampleFunction() {int cost = 5;string displayString = String.Format("Price:{0} gold",cost); }

在Unity的裝箱操作中,對(duì)于值類型會(huì)在堆內(nèi)存上分配一個(gè)System.Object類型的引用來封裝該值類型變量,其對(duì)應(yīng)的緩存就會(huì)產(chǎn)生內(nèi)存垃圾。裝箱操作是非常普遍的一種產(chǎn)生內(nèi)存垃圾的行為,即使代碼中沒有直接的對(duì)變量進(jìn)行裝箱操作,在插件或者其他的函數(shù)中也有可能會(huì)產(chǎn)生。最好的解決辦法是盡可能的避免或者移除造成裝箱操作的代碼。

2.5.4-協(xié)程

調(diào)用 StartCoroutine()會(huì)產(chǎn)生少量的內(nèi)存垃圾,因?yàn)閡nity會(huì)生成實(shí)體來管理協(xié)程。所以在游戲的關(guān)鍵時(shí)刻應(yīng)該限制該函數(shù)的調(diào)用?;诖?#xff0c;任何在游戲關(guān)鍵時(shí)刻調(diào)用的協(xié)程都需要特別的注意,特別是包含延遲回調(diào)的協(xié)程。

yield return 0;

由于需要返回0,引發(fā)了裝箱操作,所以會(huì)產(chǎn)生內(nèi)存垃圾。這種情況下,為了避免內(nèi)存垃圾,我們可以這樣返回:

yield return null;

另外一種對(duì)協(xié)程的錯(cuò)誤使用是每次返回的時(shí)候都new同一個(gè)變量,例如:

while(!isComplete) {yield return new WaitForSeconds(1f); }

我們可以采用緩存來避免這樣的內(nèi)存垃圾產(chǎn)生:

WaitForSeconds delay = new WaiForSeconds(1f); while(!isComplete) {yield return delay; }

如果游戲中的協(xié)程產(chǎn)生了內(nèi)存垃圾,我們可以考慮用其他的方式來替代協(xié)程。重構(gòu)代碼對(duì)于游戲而言十分復(fù)雜,但是對(duì)于協(xié)程而言我們也可以注意一些常見的操作,比如如果用協(xié)程來管理時(shí)間,最好在update函數(shù)中保持對(duì)時(shí)間的記錄。如果用協(xié)程來控制游戲中事件的發(fā)生順序,最好對(duì)于不同事件之間有一定的信息通信的方式。對(duì)于協(xié)程而言沒有適合各種情況的方法,只有根據(jù)具體的代碼來選擇最好的解決辦法。

2.5.5-函數(shù)引用

函數(shù)的引用,無論是指向匿名函數(shù)還是顯式函數(shù),在unity中都是引用類型變量,這都會(huì)在堆內(nèi)存上進(jìn)行分配。匿名函數(shù)的調(diào)用完成后都會(huì)增加內(nèi)存的使用和堆內(nèi)存的分配。具體函數(shù)的引用和終止都取決于操作平臺(tái)和編譯器設(shè)置,但是如果想減少GC最好減少函數(shù)的引用。

2.5.6-LINQ和常量表達(dá)式

由于LINQ和常量表達(dá)式以裝箱的方式實(shí)現(xiàn),所以在使用的時(shí)候最好進(jìn)行性能測(cè)試。

2.6-重構(gòu)代碼來減小GC的影響

即使我們減小了代碼在堆內(nèi)存上的分配操作,代碼也會(huì)增加GC的工作量。最常見的增加GC工作量的方式是讓其檢查它不必檢查的對(duì)象。struct是值類型的變量,但是如果struct中包含有引用類型的變量,那么GC就必須檢測(cè)整個(gè)struct。如果這樣的操作很多,那么GC的工作量就大大增加。在下面的例子中struct包含一個(gè)string,那么整個(gè)struct都必須在GC中被檢查:

public struct ItemData {public string name;public int cost;public Vector3 position; } private ItemData[] itemData;

我們可以將該struct拆分為多個(gè)數(shù)組的形式,從而減小GC的工作量:

private string[] itemNames; private int[] itemCosts; private Vector3[] itemPositions;

另外一種在代碼中增加GC工作量的方式是保存不必要的Object引用,在進(jìn)行GC操作的時(shí)候會(huì)對(duì)堆內(nèi)存上的object引用進(jìn)行檢查,越少的引用就意味著越少的檢查工作量。在下面的例子中,當(dāng)前的對(duì)話框中包含一個(gè)對(duì)下一個(gè)對(duì)話框引用,這就使得GC的時(shí)候回去檢查下一個(gè)對(duì)象框:

public class DialogData {private DialogData nextDialog;public DialogData GetNextDialog(){return nextDialog;} }

通過重構(gòu)代碼,我們可以返回下一個(gè)對(duì)話框?qū)嶓w的標(biāo)記,而不是對(duì)話框?qū)嶓w本身,這樣就沒有多余的object引用,從而減少GC的工作量:

public class DialogData {private int nextDialogID;public int GetNextDialogID(){return nextDialogID;} }

當(dāng)然這個(gè)例子本身并不重要,但是如果我們的游戲中包含大量的含有對(duì)其他Object引用的object,我們可以考慮通過重構(gòu)代碼來減少GC的工作量。

2.7-定時(shí)執(zhí)行GC操作

2.7.1-主動(dòng)調(diào)用GC操作

如果我們知道堆內(nèi)存在被分配后并沒有被使用,我們希望可以主動(dòng)地調(diào)用GC操作,或者在GC操作并不影響游戲體驗(yàn)的時(shí)候(例如場(chǎng)景切換的時(shí)候),我們可以主動(dòng)的調(diào)用GC操作:

System.GC.Collect()

通過主動(dòng)的調(diào)用,我們可以主動(dòng)驅(qū)使GC操作來回收堆內(nèi)存。

3-解讀Unity性能優(yōu)化

3.1-常見的Unity性能問題

VSS:Virtual Set Size,虛擬耗用內(nèi)存。它是一個(gè)進(jìn)程能訪問的所有內(nèi)存空間地址的大小。這個(gè)大小包含了 一些沒有駐留在RAM中的內(nèi)存,就像mallocs已經(jīng)被分配,但還沒有寫入。VSS很少用來測(cè)量程序的實(shí)際使 用內(nèi)存。

RSS:Resident Set Size,實(shí)際使用物理內(nèi)存。RSS是一個(gè)進(jìn)程在RAM中實(shí)際持有的內(nèi)存大小。RSS可能會(huì) 產(chǎn)生誤導(dǎo),因?yàn)樗怂性撨M(jìn)程使用的共享庫所占用的內(nèi)存,一個(gè)被加載到內(nèi)存中的共享庫可能有很 多進(jìn)程會(huì)使用它。RSS不是單個(gè)進(jìn)程使用內(nèi)存量的精確表示。

PSS:Proportional Set Size,實(shí)際使用的物理內(nèi)存,它與RSS不同,它會(huì)按比例分配共享庫所占用的內(nèi)存。 例如,如果有三個(gè)進(jìn)程共享一個(gè)占30頁內(nèi)存控件的共享庫,每個(gè)進(jìn)程在計(jì)算PSS的時(shí)候,只會(huì)計(jì)算10頁。 PSS是一個(gè)非常有用的數(shù)值,如果系統(tǒng)中所有的進(jìn)程的PSS相加,所得和即為系統(tǒng)占用內(nèi)存的總和。當(dāng)一個(gè) 進(jìn)程被殺死后,它所占用的共享庫內(nèi)存將會(huì)被其他仍然使用該共享庫的進(jìn)程所分擔(dān)。在這種方式下,PSS 也會(huì)帶來誤導(dǎo),因?yàn)楫?dāng)一個(gè)進(jìn)程被殺后,PSS并不代表系統(tǒng)回收的內(nèi)存大小。

VSS:Virtual Set Size,虛擬耗用內(nèi)存。它是一個(gè)進(jìn)程能訪問的所有內(nèi)存空間地址的大小。這個(gè)大小包含了 一些沒有駐留在RAM中的內(nèi)存,就像mallocs已經(jīng)被分配,但還沒有寫入。VSS很少用來測(cè)量程序的實(shí)際使 用內(nèi)存。

RSS:Resident Set Size,實(shí)際使用物理內(nèi)存。RSS是一個(gè)進(jìn)程在RAM中實(shí)際持有的內(nèi)存大小。RSS可能會(huì) 產(chǎn)生誤導(dǎo),因?yàn)樗怂性撨M(jìn)程使用的共享庫所占用的內(nèi)存,一個(gè)被加載到內(nèi)存中的共享庫可能有很 多進(jìn)程會(huì)使用它。RSS不是單個(gè)進(jìn)程使用內(nèi)存量的精確表示。

PSS:Proportional Set Size,實(shí)際使用的物理內(nèi)存,它與RSS不同,它會(huì)按比例分配共享庫所占用的內(nèi)存。 例如,如果有三個(gè)進(jìn)程共享一個(gè)占30頁內(nèi)存控件的共享庫,每個(gè)進(jìn)程在計(jì)算PSS的時(shí)候,只會(huì)計(jì)算10頁。 PSS是一個(gè)非常有用的數(shù)值,如果系統(tǒng)中所有的進(jìn)程的PSS相加,所得和即為系統(tǒng)占用內(nèi)存的總和。當(dāng)一個(gè) 進(jìn)程被殺死后,它所占用的共享庫內(nèi)存將會(huì)被其他仍然使用該共享庫的進(jìn)程所分擔(dān)。在這種方式下,PSS 也會(huì)帶來誤導(dǎo),因?yàn)楫?dāng)一個(gè)進(jìn)程被殺后,PSS并不代表系統(tǒng)回收的內(nèi)存大小。

3.2-Unity運(yùn)行時(shí)的內(nèi)存占用情況

3.3-內(nèi)存標(biāo)準(zhǔn)

  • 限定內(nèi)存占用不超過200M(iPhone4接近容易Crash,低端機(jī)型)
  • 項(xiàng)目中Reserved Total(總體分配)內(nèi)存盡量控制在150M以內(nèi),如下 Texture 50M Mesh 20M AnimationClip 15M AudioClip 15M Mono堆內(nèi)存 40M 字體等 10M
  • 項(xiàng)目中盡量嚴(yán)格控制,即使在中高端機(jī)型可較大內(nèi)存運(yùn)行。

3.4-Mono內(nèi)存管理策略

  • 字符串連接處理,建議StringBuilder
  • 盡量不使用foreach,Unity5.4以上解決了GC問題
  • 不要頻繁實(shí)例化和銷毀對(duì)象,建議對(duì)象池管理
  • 場(chǎng)景切換時(shí),主動(dòng)調(diào)用System.GC.Collect(),及時(shí)清理內(nèi)存

  • Mono通過垃圾回收機(jī)制(Garbage Collect,簡(jiǎn)稱GC)對(duì)內(nèi)存進(jìn)行管理。Mono內(nèi)存分為兩部分,已用內(nèi)存(used)和堆內(nèi)存(heap),已用內(nèi)存指的是mono實(shí)際需要使用的內(nèi)存,堆內(nèi)存指的是mono向操作系統(tǒng)申請(qǐng)的內(nèi)存,兩者的差值就是mono的空閑內(nèi)存。當(dāng)mono需要分配內(nèi)存時(shí),會(huì)先查看空閑內(nèi)存是否足夠,如果足夠的話,直接在空閑內(nèi)存中分配,否則mono會(huì)進(jìn)行一次GC以釋放更多的空閑內(nèi)存,如果GC之后仍然沒有足夠的空閑內(nèi)存,則mono會(huì)向操作系統(tǒng)申請(qǐng)內(nèi)存。

3.5-Mono內(nèi)存泄漏分析

  • Mono通過引用關(guān)系,判斷哪些內(nèi)存不再使用
  • 【Mono內(nèi)存泄漏】對(duì)象已經(jīng)不再使用,卻未被GC回收
  • Mono內(nèi)存泄漏使空閑內(nèi)存減少,GC頻繁,mono堆不斷擴(kuò)大,最終導(dǎo)致游戲內(nèi)存占用的增大
  • 大部分mono內(nèi)存泄漏的情況都是由于靜態(tài)對(duì)象的引用引起
  • 不再需要的對(duì)象將其引用設(shè)置為null,使其可以被GC及時(shí)回收

3.6-優(yōu)化

3.6.1-DrawCall優(yōu)化

  • 先了解下DrawCall相關(guān)概念,便于優(yōu)化

    DrawCall是CPU調(diào)用底層圖形接口的操作

    DrawCall_Num = 25K * CPU_Frame * CPU_Percentage / FPS

    DrawCall_Num : DrawCall數(shù)量(最大支持)

    CPU_Frame : CPU 工作頻率(GHz單位)

    CPU_Percentage:CPU 分配在DrawCall這件事情上的時(shí)間率 (百分比) FPS:希望的游戲幀率

  • DrawCall Batching(DC批處理)

    Dynamic Batching(動(dòng)態(tài)批處理)

    Static Batching(靜態(tài)批處理)

  • Bus總線帶寬

    CPU完成一次DrawCall,除了需要調(diào)用一次DrawCall的命令之外,還需要把內(nèi)存中頂點(diǎn)數(shù)據(jù)、紋理貼圖、shader參數(shù)通過bus總線拷貝到內(nèi)存分配給GPU的顯存之中,注意這是拷貝,不是指針傳遞,速度不快。項(xiàng)目中不會(huì)同時(shí)出現(xiàn)的資源不要打包到一起,保證單張合并紋理不大于1024*1024一般就不會(huì)有問題了。

3.6.2-CPU優(yōu)化最直接的方法

  • VSync(垂直同步)是CPU優(yōu)化最直接的方式(發(fā)熱、耗電原因之一)

  • 打開Edit-Project Settings-Quality找到V Sync Count

    V Sync Count

    Don’t Sync 不同步

    Every V Blank 每一個(gè)垂直同步

    Every Second V Blank 每一秒垂直同步

通常我們選擇Don’t Sync,同時(shí)Application.targetFrameRate設(shè)置目標(biāo)FPS,讓性能保持一個(gè)好的狀態(tài)。注意選擇其他項(xiàng),Application.targetFrameRate設(shè)置不生效。

垂直同步講會(huì)在下節(jié)“5.2-Unity Profile中詳細(xì)介紹”

3.6.3-GPU優(yōu)化

渲染流程

GPU接收頂點(diǎn)數(shù)據(jù)作為輸入傳遞給頂點(diǎn)著色器。頂點(diǎn)著色器的處理單元是頂點(diǎn),輸入進(jìn)來的每個(gè)頂點(diǎn)都會(huì)調(diào)用一次頂點(diǎn)著色器。(頂點(diǎn)著色器本身不可以創(chuàng)建或銷毀任何頂點(diǎn),并無法得到頂點(diǎn)與頂點(diǎn)之間的關(guān)系)。頂點(diǎn)著色器是完全可編程的,它主要完成的工作有:坐標(biāo)變換和逐頂點(diǎn)光照。 坐標(biāo)變換:就是對(duì)頂點(diǎn)的坐標(biāo)進(jìn)行某種變換—把頂點(diǎn)坐標(biāo)從模型空間轉(zhuǎn)換到齊次裁剪空間。頂點(diǎn)的多少直接決定了三角形面的多少,也直接決定了GPU的渲染流水線的工作量,所以減少頂點(diǎn)數(shù)是一個(gè)比較重要的優(yōu)化點(diǎn)。那么減少頂點(diǎn)怎么操作呢,又有哪些途徑?

  • 頂點(diǎn)著色器 優(yōu)化基本幾何體(模型減面減頂點(diǎn)) 使用LOD(Level of detail)技術(shù) 使用遮擋剔除(Occlusion culling)技術(shù)
  • 中間操作 曲面細(xì)分著色器:是一個(gè)可選的著色器,主要用于細(xì)分圖元 幾何著色器:是一個(gè)可選的著色器,可用于執(zhí)行逐圖元的著色操作,或者被用于產(chǎn)生更多的圖元。 裁剪:這一階段是可配置的。目的是把那些不在視野內(nèi)的頂點(diǎn)裁剪掉,并剔除某些三角形圖元的面片。部分在視野內(nèi)的圖元需要做裁剪處理,在裁剪邊緣產(chǎn)生新的頂點(diǎn)和三角形進(jìn)行處理。 屏幕映射:這一階段是可配置和編程的,負(fù)責(zé)把每個(gè)圖元的坐標(biāo)(三維坐標(biāo)系)轉(zhuǎn)換成屏幕坐標(biāo)(二維坐標(biāo)系)。
  • 三角形設(shè)置:開始進(jìn)入光柵化階段,不再是數(shù)學(xué)上點(diǎn)了,而會(huì)把所有的點(diǎn)都映射到屏幕的具體像素坐標(biāo)上,計(jì)算每條邊上的像素坐標(biāo)而得到三角形邊界的表示方式即為三角形設(shè)置。 三角形遍歷:這一階段會(huì)檢查每個(gè)像素是否被一個(gè)三角風(fēng)格所覆蓋。如果覆蓋的話,就會(huì)生成一個(gè)片元(一個(gè)片元并不是真正意義上的像素,而是包含了很多狀態(tài)的集合,這些狀態(tài)用于計(jì)算每個(gè)像素的最終顏色。這些狀態(tài)包括了屏幕坐標(biāo)、深度信息,及從幾何階段輸出的頂點(diǎn)信息,如法線和紋理坐標(biāo)等。),這樣一個(gè)查找哪些像素被三角形覆蓋的過程就是三角形遍歷。
  • 片元著色器 盡量減少overdraw 減少實(shí)時(shí)光照 不要使用動(dòng)態(tài)陰影 盡量使用簡(jiǎn)單的shader

片元著色器的輸入就是上一階段對(duì)頂點(diǎn)信息插值得到的結(jié)果,更具體點(diǎn)說,是根據(jù)從頂點(diǎn)著色器中輸出的數(shù)據(jù)插值得到的。而這一階段的輸出是一個(gè)或者多個(gè)顏色值。這一階段可以完成很多重要的渲染技術(shù),如紋理采樣,但是它的局限在于,它僅可以影響單個(gè)片元。片元著色器是比較花時(shí)間的,因?yàn)樗亲罱K顏色的計(jì)算者,在某些情況下,例如復(fù)雜燈光環(huán)境下,片元著色器會(huì)出現(xiàn)GPU流水線主要的拖后腿的存在。為了讓片元著色器的計(jì)算更加快,我們需要從很多方面進(jìn)行提前的優(yōu)化:片元著色器最容易拖后腿的情況就是,overdraw!和Android app的開發(fā)一樣,就是同一個(gè)像素點(diǎn)繪制了多次,某些情況會(huì)造成計(jì)算力的浪費(fèi),增加耗電量。前面提到的遮擋剔除有減少overdraw非常有用。在PC上,資源無限,為了得到最準(zhǔn)確的渲染結(jié)果,繪制順序可能是從后往前繪制不透明物體,然后再繪制透明物體進(jìn)行混合。但是在移動(dòng)平臺(tái)上,對(duì)于不透明物體,我們可以設(shè)置從前往后繪制,對(duì)于有透明通道的物體(很多UI紋理就是含有透明通道的),再設(shè)置從后往前繪制。unity中shader設(shè)置為“Geometry” 隊(duì)列的對(duì)象總是從前往后繪制的,而其他固定隊(duì)列(如“Transparent”“Overla”等)的物體,則都是從后往前繪制的。這意味這,我們可以盡量把物體的隊(duì)列設(shè)置為“Geometry” 。對(duì)于GUI,尤其要注意和設(shè)計(jì)師商量,能用不透明的設(shè)計(jì)就用不透明的,對(duì)于粒子效果,也要注意不要引入透明值,多半情況下,移動(dòng)平臺(tái)的粒子效果透明值沒有作用。

移動(dòng)平臺(tái)的最大敵人。一個(gè)場(chǎng)景里如果包含了三個(gè)逐像素的點(diǎn)光源,而且使用了逐像素的shader,那么很有可能將Draw Calls提高了三倍,同時(shí)也會(huì)增加overdraws。這是因?yàn)?#xff0c;對(duì)于逐像素的光源來說,被這些光源照亮的物體要被再渲染一次。更糟糕的是,無論是動(dòng)態(tài)批處理還是動(dòng)態(tài)批處理(其實(shí)文檔中只提到了對(duì)動(dòng)態(tài)批處理的影響,但不知道為什么實(shí)驗(yàn)結(jié)果對(duì)靜態(tài)批處理也沒有用),對(duì)于這種逐像素的pass都無法進(jìn)行批處理,也就是說,它們會(huì)中斷批處理。所以當(dāng)你需要光照效果時(shí),可以使用Lightmaps,提前烘焙好,提前把場(chǎng)景中的光照信息存儲(chǔ)在一張光照紋理中,然后在運(yùn)行時(shí)刻只需要根據(jù)紋理采樣得到光照信息即可。當(dāng)你需要金屬性強(qiáng)(鏡面)的效果,可以使用Light Probes。當(dāng)你需要一束光的時(shí)候,可以使用體積光去模擬這個(gè)效果。

動(dòng)態(tài)陰影很酷,但是對(duì)于片元著色器來說是災(zāi)難,陰影計(jì)算是三角投影計(jì)算,非常耗性能。如果想要陰影,可以使用

  • 簡(jiǎn)單的使用一個(gè)帶陰影的貼圖
  • 烘焙場(chǎng)景,拿到lightmaps
  • 創(chuàng)建投影生成器的方法
  • 使用ShadowMap的方法
  • 建議盡量使用Unity自帶mobile版本的(built-in)Shader,這些大大提高了頂點(diǎn)處理的性能。當(dāng)然也會(huì)有一些限制。
  • 自己寫的shader請(qǐng)注意復(fù)雜操作符計(jì)算,類似pow,exp,log,cos,sin,tan等都是很耗時(shí)的計(jì)算,最多只用一次在每個(gè)像素點(diǎn)的計(jì)算,還有有些除法運(yùn)算盡量該能乘法運(yùn)算等。
  • 避免透明度測(cè)試著色器,因?yàn)檫@個(gè)非常耗時(shí),使用透明度混合的版本來代替。
  • 浮點(diǎn)類型運(yùn)算:精度越低的浮點(diǎn)計(jì)算越快。
  • 不要在Shader中添加不必要的Pass.
  • 3.7-研發(fā)團(tuán)隊(duì)需要關(guān)注的引擎模塊

    3.8-開始優(yōu)化工作

    前面已經(jīng)介紹了性能相關(guān)概念以及需關(guān)注模塊,接下來該開始優(yōu)化工作,具體步驟如下:

    4-Unity3D性能優(yōu)化——初識(shí)Unity-Statistics

    當(dāng)運(yùn)行一個(gè)U3D場(chǎng)景后,可以在界面右上方看到一個(gè)叫做"Status"的按鈕,點(diǎn)開它就會(huì)出現(xiàn)一個(gè)重疊界面顯示出實(shí)時(shí)統(tǒng)計(jì)數(shù)據(jù),比如下圖這種樣子:

    ? 如果你是一名U3D開發(fā)新手,或者對(duì)此功能非常不熟悉,那么你可能會(huì)在游戲優(yōu)化過程中遇到很多麻煩。接下來的篇幅著重講講該窗口的作用和必要的相關(guān)名詞解釋。

    ? Statistics窗口,全稱叫做 Rendering Statistics Window,即渲染統(tǒng)計(jì)窗口(或渲染數(shù)據(jù)統(tǒng)計(jì)窗口),窗口中羅列出關(guān)于聲音、圖像、網(wǎng)絡(luò)狀況等多種統(tǒng)計(jì)信息

    • FPS(Time per frame andFPS):frames per seconds表示引擎處理和渲染一個(gè)游戲幀所花費(fèi)的時(shí)間,該數(shù)字主要受到場(chǎng)景中渲染物體數(shù)量和 GPU性能的影響,FPS數(shù)值越高,游戲場(chǎng)景的動(dòng)畫顯示會(huì)更加平滑和流暢。一般來說,超過30FPS的畫面人眼不會(huì)感覺到卡,由于視覺殘留的特性,光在視網(wǎng)膜上停止總用后人眼還會(huì)保持1/24秒左右的時(shí)間,因此游戲畫面每秒幀數(shù)至少要保證在30以上。另外,Unity中的FPS數(shù)值僅包括此游戲Scene里更新和渲染的幀,編輯器中繪制的Scene和其它監(jiān)視窗口的進(jìn)程不包括在內(nèi)。
    • CPU:獲取到當(dāng)前占用CPU進(jìn)行計(jì)算的時(shí)間絕對(duì)值,或時(shí)間點(diǎn),如果Unity主進(jìn)程處于掛斷或休眠狀態(tài)時(shí),CPU time將會(huì)保持不變。
    • Render thread:GPU渲染線程處理圖像所花費(fèi)的時(shí)間,具體數(shù)值由GPU性能來決定,
    • Batches:即Batched Draw Calls,是Unity內(nèi)置的Draw Call Batching技術(shù)。

    ? 首先解釋下什么叫做“Draw call”,CPU每次通知GPU發(fā)出一個(gè)glDrawElements(OpenGl中的圖元渲染函數(shù))或DrawIndexedPrimitive(DirectX中的頂點(diǎn)繪制方法)的過程稱為一次Draw call,一般來說,引擎每對(duì)一個(gè)物體進(jìn)行一次DrawCall,就會(huì)產(chǎn)生一個(gè)Batch,這個(gè)Batch里包含著該物體所有的網(wǎng)格和頂點(diǎn)數(shù)據(jù),當(dāng)渲染另一個(gè)相同的物體時(shí),引擎會(huì)直接調(diào)用Batch里的信息,將相關(guān)頂點(diǎn)數(shù)據(jù)直接送到GPU,從而讓渲染過程更加高效,即Batching技術(shù)是將所有材質(zhì)相近的物體進(jìn)行合并渲染。

    ? 對(duì)于含有多個(gè)不同Shader和Material的物體,渲染的過程比較耗時(shí),因?yàn)闀?huì)產(chǎn)生多個(gè)Batches。每次對(duì)物體的材質(zhì)或者貼圖進(jìn)行修改,都會(huì)影響B(tài)atches里數(shù)據(jù)集的構(gòu)成。因此,如果場(chǎng)景中有大量材質(zhì)不同的物體,會(huì)很明顯的影響到GPU的渲染效率。這里說幾點(diǎn)關(guān)于Batches優(yōu)化相關(guān)的方案。

    雖然Unity引擎自帶Draw Call Batching技術(shù),我們也可以通過手動(dòng)的方式合并材質(zhì)接近的物體;

    盡量不要修改Batches里物體的Scale,因?yàn)檫@樣會(huì)生成新的Batch。

    為了提升GPU的渲染效率,應(yīng)當(dāng)盡可能的在一個(gè)物體上使用較少的材質(zhì),減少Batches過多的開銷;

    對(duì)于場(chǎng)景中不會(huì)運(yùn)動(dòng)的物體,考慮設(shè)置Static屬性,Static聲明的物體會(huì)自動(dòng)進(jìn)行內(nèi)部批處理優(yōu)化。

    • Verts:攝像機(jī)視野(field of view)內(nèi)渲染的頂點(diǎn)總數(shù)。
    • Tris: 攝像機(jī)視野(field of view)內(nèi)渲染的的三角面總數(shù)量。

    ? 關(guān)于Tris和Verts,突然想到一些問題,這里需要多嘴說幾句:

    Camera的渲染性能受到Draw calls的影響。之前說過,對(duì)一個(gè)物體進(jìn)行渲染,會(huì)生成相應(yīng)的Draw call,處理一個(gè)Draw Call的時(shí)間是由它上邊的Tris和Verts數(shù)目決定。盡可能得合并物體,會(huì)很大程度的提高性能。舉個(gè)很簡(jiǎn)單例子,比如場(chǎng)景一種有1000個(gè)不同的物體,每個(gè)物體都有10個(gè)Tris;場(chǎng)景二中有10個(gè)不同的物體,每個(gè)物體有1000個(gè)Tris。在渲染處理中,場(chǎng)景一中會(huì)產(chǎn)生1000個(gè)Draw Calls,它的渲染時(shí)間明顯比場(chǎng)景二慢。

    Unity stats 視圖中的 Tris 和 Verts 并不僅僅是視錐中的梯形內(nèi)的 Tris 和 Verts,而是Camera中 field of view所有取值下的tris和verts,換句話說,哪怕你在當(dāng)前game視圖中看不到這個(gè) cube,如果當(dāng)你把 field of view調(diào)大到 179 過程中都看不到這個(gè)cube,stats面板才不會(huì)統(tǒng)計(jì),GPU才不會(huì)渲染,否則都會(huì)渲染,而且unity不會(huì)把模型拆分,這個(gè)模型哪怕只有1個(gè)頂點(diǎn)需要渲染,unity也會(huì)把整個(gè)模型都渲出來。(參考自Mess的《Unity Camera組件部分參數(shù)詳解》)

    之前有童鞋問過我,新建一個(gè)空的場(chǎng)景,里邊沒有添加任何物體,為什么Status面板上顯示有1.7k Tris以及5.0kVerts。這是因?yàn)榭盏膱?chǎng)景自帶默認(rèn)的天空盒。點(diǎn)擊Windows—Lighting打開Lighting下的Scene面板,把Skybox里的材質(zhì)設(shè)為空,比如像我下圖這樣:**

    ? 可以看到,場(chǎng)景中的Tris數(shù)量變?yōu)?,Verts數(shù)量變?yōu)榱?,這是由于攝像機(jī)存在的關(guān)系,刪掉它,你就會(huì)發(fā)現(xiàn)Tris 和 Verts 都變?yōu)?了。

    • Screen:獲當(dāng)前Game屏幕的分辨率大小,后邊的2.1MB表示總的內(nèi)存使用數(shù)值。
    • SetPass calls:又碰到一個(gè)神奇的詞“SetPass calls”。如果你是一個(gè)Unity的老用戶,你可能會(huì)注意到原來的Stats面板的第一項(xiàng)是“Draw calls”,然而到了Unity5.X版本,Stats上沒有了“Draw calls”,卻多出來一項(xiàng)”SetPass calls“,那么這個(gè)玩意到底是做什么的???(你猜… )← ←!

    ? 感覺又要說一大堆東西了…之前有講到Batches,比如說場(chǎng)景中有100個(gè)gameobject,它們擁有完全一樣的Material,那么這100個(gè)物體很可能會(huì)被Unity里的Batching機(jī)制結(jié)合成一個(gè)Batch。所以用“Batches”來描述Unity的渲染性能是不太合適的,它只能反映出場(chǎng)景中需要批處理物體的數(shù)量。那么可否用“Draw calls”來描述呢?答案同樣是不適合。每一個(gè)“Draw calls”是CPU發(fā)送個(gè)GPU的一個(gè)渲染請(qǐng)求,請(qǐng)求中包括渲染對(duì)象所有的頂點(diǎn)參數(shù)、三角面、索引值、圖元個(gè)數(shù)等,這個(gè)請(qǐng)求并不會(huì)占用過多的消耗,真正消耗渲染資源的是在GPU得到請(qǐng)求指令后,把指令發(fā)送給對(duì)應(yīng)物體的Shader,讓Shader讀取指令并通知相應(yīng)的渲染通道(Pass)進(jìn)行渲染操作。

    • Shadow casters:表示場(chǎng)景中有多少個(gè)可以投射陰影的物體,一般這些物體都作為場(chǎng)景中的光源。
    • visible skinned meshed:渲染皮膚網(wǎng)格的數(shù)量。
    • Animations:正在播放動(dòng)畫的數(shù)量。

    5-Unity3D性能優(yōu)化——Unity篇

    5.1-Unity 腳本開發(fā)方面

    基本思想減少動(dòng)態(tài)內(nèi)存分配和釋放,減少耗時(shí)函數(shù)的調(diào)用,盡可能的使用緩存。

    1:控制Startcorountien 的使用次數(shù),避免頻繁的開啟協(xié)程,開啟一個(gè)協(xié)程至少分配37B的內(nèi)存空間(corountien類的實(shí)例 分配21B Enumerator 分配16B)
    如果僅僅是延遲運(yùn)行,定時(shí)運(yùn)行函數(shù),可以使用invoke invokerepeating 代替

    2:對(duì)象查找 gameobject.find(); 全局的查找方式,無法查找隱藏的對(duì)象,效率低下
    Transform.find 從自身位置查找,性能較優(yōu)的推薦方法
    Gameobject.findobjectswithTag 通過標(biāo)簽查找,效率較高,但是需要設(shè)置標(biāo)簽稍顯麻煩。
    建議在Awake 或者Start 函數(shù)中查找對(duì)象并保存引用,切忌在Update中動(dòng)態(tài)的查找

    3:緩存組件
    注意獲取組件的方法GetCompent 方法大約會(huì)分配39B的堆內(nèi)存,并且GetCompent是去訪問unity原生代碼效率很低,使用緩存訪問,性能相差幾十倍。緩存訪問性能要高得多。
    (a)盡量避免在Update函數(shù)中做計(jì)算,可以使用InvokeRepeating,間隔一段計(jì)算一次。
    (b)避免使用SendMessage 性能底下,使用了反射機(jī)制,要使用委托 delegate的事件模擬消息機(jī)制。
    (c)刪除無用的預(yù)制體上的組件,刪除類中無用的函數(shù)。
    (d)腳本的禁用,腳本使用的時(shí)候開啟,不用的時(shí)候關(guān)閉,需要專門寫一套管理機(jī)制。

    4.減少.Count .Length的調(diào)用

    for(int i = 0; i < list.Count; i++) { //do something}

    應(yīng)改為:

    for(int i = 0, j = list.Count; i < j ; i++) { //do something}

    5.減少 gameobject,transform,GetComponent 的使用

    我們可以在Start()方法中預(yù)先存儲(chǔ)好這些值,之后使用的時(shí)候調(diào)用預(yù)先存儲(chǔ)好的值即可。

    GameObject m_gameObject; Transform m_transform; Text m_text; void Start () { m_gameObject = gameObject; m_transform = transform; m_text = GetComponent<Text>(); }

    6.減少SetActive(bool)的使用

    對(duì)于要頻繁顯示隱藏的物體,我們可以減少使用SetActive(bool),而是通過transform.scale信息將其縮小為0,例如UI的隱藏。

    7.如果某個(gè)活動(dòng)狀態(tài)(gameObject.active == true)的GameObject上的腳本中含有Awake()方法,即使這個(gè)腳本沒有被啟用(enabled==false),Awake()方法也會(huì)執(zhí)行。如果游戲中含有非常多的帶有Update()方法的MonoBehavior,應(yīng)該嘗試改變代碼結(jié)構(gòu)來減少開銷,

    8.Camera.main所引起的問題與Find()方法類似,應(yīng)該避免使用Camera.main并且手動(dòng)管理對(duì)相機(jī)的引用。

    9.Update()和LateUpdate()等事件方法的每次調(diào)用都需要引擎代碼與托管代碼之間進(jìn)行通信,還要Unity進(jìn)行安全檢查(GameObject狀態(tài)是否合法等),即使這些事件方法的方法體是空的,引擎任然會(huì)對(duì)其進(jìn)行調(diào)用。因此,為避免浪費(fèi)CPU時(shí)間,應(yīng)該 刪除空的事件方法

    10.設(shè)置position和rotation會(huì)觸發(fā)內(nèi)部的OnTransformChanged事件并傳播到所有的子級(jí)對(duì)象中,對(duì)于含有非常對(duì)子物體的對(duì)象來說,這種操作開銷很大,應(yīng)該 減少對(duì)position和rotation的修改。

    11.嘗試使用localPosition替代position。localPosition存儲(chǔ)在transform中,訪問該值時(shí),Unity會(huì)直接將其返回,而position在每次訪問時(shí)都會(huì)重新計(jì)算,如果要經(jīng)常獲取position,可以將其緩存起來。

    12.不要附加 Animation Component 在靜態(tài)實(shí)體上附加 Animation 部件雖然對(duì)結(jié)果沒有影響,但卻會(huì)增加一定的 CPU 開銷來調(diào)用這一組件,所以盡量去掉該組件。

    13.關(guān)于相機(jī)相機(jī)
    裁剪平面
    將遠(yuǎn)平面設(shè)置成合適的距離。遠(yuǎn)平面過大會(huì)將一些不必要的物體加入渲染,降低效率。
    根據(jù)不同的物體設(shè)置不同的遠(yuǎn)裁剪平面
    Unity 提供了可以根據(jù)不同的 layer 來設(shè)置不同的 view distance ,所以我們可以實(shí)現(xiàn)將物體進(jìn)行分層,大物體層設(shè)置的可視距離大些,而小物體層可以設(shè)置地小些,另外,一些開銷比較大的實(shí)體(如粒子系統(tǒng))可以設(shè)置得更小些等等。

    14.非運(yùn)動(dòng)物體盡量打上 Static 標(biāo)簽
    Unity 在運(yùn)行時(shí)會(huì)對(duì) static 物體進(jìn)行自動(dòng)優(yōu)化處理,所以應(yīng)該盡可能將非運(yùn)行實(shí)體勾上 static 標(biāo)簽。

    15.不要實(shí)例化(Instantiate)對(duì)象,事先建好對(duì)象池,并使用Translate“生成”對(duì)象;

    16.使用 Resource.Load 方法在需要的時(shí)候再讀取資源;各種資源在使用完成后,盡快用Resource.UnloadAsset和UnloadUnusedAsset卸載掉;

    17.靈活運(yùn)用AssetBundle的Load和Unload方法動(dòng)態(tài)加載資源,避免主要場(chǎng)景內(nèi)的初始化內(nèi)存占用過高;(實(shí)現(xiàn)起來真的很難…)

    18.采用www加載了AssetBundle后,要用www.Dispose 及時(shí)釋放;

    19.在關(guān)卡內(nèi)謹(jǐn)慎使用DontDestroyOnLoad,被標(biāo)注的資源會(huì)常駐內(nèi)存;

    20.盡量少使用FindObjectsOfType函數(shù),這個(gè)函數(shù)非常慢,盡量少用且一定不要在Update里調(diào)用;

    21.場(chǎng)景中若存在不需要顯示的模型,盡量不使用SetActive方法,而是將其Scale置為Vectory.Zero,并禁用其MeshRenderer

    24.場(chǎng)景中絕對(duì)靜態(tài)的模型可以使用合并Mesh操作來進(jìn)行減少DrawCall

    private void CombineMesh(){ for (int i = 0; i < rootTr.Count; i++){GameObject rootModel = rootTr[i].gameObject;//給父物體添加meshfilterMeshFilter combineMeshFilter = rootModel.GetComponent<MeshFilter>();if (combineMeshFilter == null){combineMeshFilter = rootModel.AddComponent<MeshFilter>();}//獲取子物體中所有的meshfiltervar filters = rootModel.GetComponentsInChildren<MeshFilter>();//將子物體的meshfilter添加到combineInstance中CombineInstance[] combines = new CombineInstance[filters.Length];for (int j = 0; j < filters.Length; j++){combines[j].mesh = filters[j].sharedMesh;combines[j].transform = filters[j].transform.localToWorldMatrix;}//合并mesh并將mesh賦值給父物體Mesh finalmesh = new Mesh(); finalmesh.CombineMeshes(combines);rootModel.gameObject.GetComponent<MeshFilter>().sharedMesh = finalmesh;}}

    25.支持分級(jí)Log(自定義logger),避免大量且頻繁的Log,在構(gòu)建時(shí)屏蔽log。

    26.使用gameObject.CompareTag(“XXX”)而非gameObject.tag,后者會(huì)產(chǎn)生額外的內(nèi)存與性能消耗。

    27.使用內(nèi)建的常量,例如Vector3.zero等等,避免頻繁創(chuàng)建相同的對(duì)象。

    5.2-Unity資源相關(guān)優(yōu)化

    這節(jié)主要講unity資源優(yōu)化,先學(xué)習(xí)一個(gè)概念:資源管道,原始文件通過內(nèi)容管道變成了一個(gè)可被Unity高效使用的中間文件 ,這不是Unity里面的一個(gè)概念,但Unity的工作行為和它很類似;Unity在導(dǎo)入資源的時(shí)候可以使用類型豐富的文件,這不意味著在我們生成的App中同樣也是這些文件,資源通過Unity的資源管道變成了較為統(tǒng)一的格式。我們?cè)趯?dǎo)入資源的時(shí)候有很多參數(shù)可以調(diào)整,

    5.2.1-音頻

    在Unity中導(dǎo)入聲音文件我們能看到類似下面的面板 , 我們先看第一個(gè)選擇Load Type,他有三個(gè)可值:

    Decompress On Load,Compressed In Memory ,Streaming。

    Decompress On Load

    在硬盤上壓縮這個(gè)文件,并在第一次加載到內(nèi)存的時(shí)候解壓它,這是加載聲音文件的默認(rèn)選項(xiàng),大多數(shù)情況下我們應(yīng)該使用這個(gè)選擇 。

    加載后解壓縮聲音,聲音文件將在他們加載不久后就解壓,這個(gè)選項(xiàng)適用于較小的壓縮聲音,以避免即時(shí)解壓縮的性能開銷。要知道在加載時(shí)解壓 Vorbis編碼的聲音將使用的內(nèi)存是壓縮狀態(tài)的十倍或更多(ADPCM編碼大概3.5倍)所以不要使用此選項(xiàng)用于大文件。

    Decompress On Load 默認(rèn)選項(xiàng)適用于小文件。

    ? Compressed In Memory

    ? 保持聲音在內(nèi)存中是壓縮的并在播放時(shí)解壓縮。這有更多的CPU開銷(尤其是OGG / Vorbis格式的壓縮文件),但可以提高加載速度并減少內(nèi)存消 耗,因此這個(gè)選項(xiàng)適用于大文件。在性能窗口可以看"DSP CPU"。

    ? Compressed In Memory 適用于大文件。

    ? Streaming 選項(xiàng)

    ? 直接從磁盤流音頻數(shù)據(jù)。這只使用了原始聲音占內(nèi)存大小的很小一部分。 該方法使用最少的內(nèi)存和最多的CPU,它有個(gè)很明顯的缺點(diǎn)就是不能被引用超過一次。試著讓 Audio Clip產(chǎn)生多個(gè)副本的時(shí)候會(huì)每個(gè)都產(chǎn)生數(shù)據(jù)緩沖區(qū),如果非要這么做會(huì)產(chǎn)生大量的內(nèi)存和cpu消耗。因此這個(gè)選擇最好是給單實(shí)例的Audio Clip,如背景和環(huán)境音效。對(duì)于手游而言不要優(yōu)先考慮使用這種方式。

    在場(chǎng)景中把一個(gè)Audio Clip賦值給Audio Source組件,這個(gè)音頻文件將在場(chǎng)景初始化的時(shí)候加載到內(nèi)存中。但是如果它啟用了,加載Audio Clip就變成了一個(gè)后臺(tái)任務(wù)它將推遲到場(chǎng)景初始化完成后再加載,換句話說就是在游戲開始后開始加載。 通過啟用這個(gè)選擇我們可以提高場(chǎng)景的啟動(dòng)速度,但Play聲音的時(shí)候它還在后臺(tái)加載的話播放將推遲到加載完成,我們可以使用AudioClip對(duì)象的loadState 屬性來檢查是否加載完成以保證聲音在不會(huì)在一個(gè)不恰當(dāng)?shù)臅r(shí)間播放。

    ? Preload Audio Data 默認(rèn)是啟用的,它表示Unity自動(dòng)在場(chǎng)景初始化時(shí)加載文件。禁用此選項(xiàng)將推遲加載直到 AudioSource的 Play() 或 PlayOneShot() 方法執(zhí)行的時(shí)候。從硬盤加載聲音文件,然后解壓,再push到內(nèi)存里然后再播放,這么一系列的動(dòng)作可能 會(huì)導(dǎo)致 CPU的峰值。

    ? 由于播放延遲和性能消耗,不建議在播放的瞬間加載。我們應(yīng)該控制加載在播放之前的某些方便的時(shí)間使用AudioClip對(duì)象的LoadAudioData()方法加載。我們也可以用AudioClip對(duì)象的UnloadAudioData()方法手動(dòng)控制聲音文件的內(nèi)存釋放。

    ? 聲音文件的編碼格式和質(zhì)量

    ? Unity支持三種聲音文件編碼格式的,由于平臺(tái)依賴性在某些特殊情況下會(huì)有其他的選項(xiàng)(如Xbox One的XMA和PS Vita的HEVAG )

    • Vorbis/MP3
    • PCM
    • ADPCM

    ? 我們導(dǎo)入到Unity的音頻文件可能是各種各樣常見的音頻格式,但通過內(nèi)容管道,Standalone、WebGL和其他的一些非移動(dòng)平臺(tái)使用Ogg-Vorbis格式的壓縮,而移動(dòng)平臺(tái)使用MPEG-3(MP3)格式。

    ? PCM 提供高品質(zhì)但犧牲文件大小最適合使用在很短的音效上。

    ? ADPCM 這種格式適用于大量音效上如腳步爆破和武器,它比PCM小3.5倍但CPU使用率遠(yuǎn)低于Vorbis/MP3

    ? Vorbis/MP3 比PCM小但是品質(zhì)比PCM低,比ADPCM消耗更多CPU。但大多數(shù)情況下我們還是應(yīng)該使用這種格式,這個(gè)選擇還多了個(gè)Quality可以調(diào)節(jié)質(zhì)量改變文件大小增強(qiáng)音頻性能

    **盡量減少音頻數(shù)量 **

    ? 因?yàn)槊總€(gè) Audio Source的播放都會(huì)消耗一定量的cpu,所以我們可以控制場(chǎng)景中 Audio Source的數(shù)量來節(jié)省cpu。

    ? 一種方式是控制我們的音頻來源,這種方式我們硬盤上 的AudioClip可以同時(shí)播放的數(shù)量和總共播放的總數(shù)進(jìn)行節(jié)流控制。我們通常會(huì)做一個(gè)AudioPool做這些節(jié)流操作,這很適合2d聲音和單實(shí)例的3d聲音(3d聲音在播放的時(shí)候仍然要放在場(chǎng)景中具體的位置 )。 更甚至是移除一些音頻,這種做法會(huì)影響到用戶體驗(yàn),我們應(yīng)該在質(zhì)量和性能上做權(quán)衡。

    減少AudioClip引用

    ? 場(chǎng)景中每個(gè)Audio Source的Audio Clip引用和Preload Audio Data 啟用都將消耗一定量的內(nèi)存(壓縮解壓或者緩存),這些內(nèi)存將貫徹整個(gè)場(chǎng)景,如果兩個(gè)或兩個(gè)以上的Audio Source引用相同的Audio Clip沒有額外的內(nèi)存消耗。Audio Clips在Unity中是非托管資源這意味著他們不會(huì)通過設(shè)置為null釋放內(nèi)存。

    ? Unity希望我們能夠加載和釋放這些資源,經(jīng)常使用的音效長(zhǎng)久的在內(nèi)存中保存文件是合理的,因?yàn)槊看渭虞d一個(gè)文件到

    ? 內(nèi)存中都會(huì)消耗CPU。然而,如果我們發(fā)現(xiàn)因?yàn)橐粜Ф褂锰嗟膬?nèi)存的時(shí)候,我們必須做出艱難的選擇是降低音頻質(zhì)量還是完全移除他們來節(jié)省內(nèi)存。另一方面,保存不常用的音效在一個(gè)很長(zhǎng)的場(chǎng)景中將會(huì)造成重大問題。

    ? 我們可能會(huì)有很多一次性音效,如對(duì)話片段,它們沒有需 要長(zhǎng)久保存在內(nèi)存中。創(chuàng)建Audio Sources并分配一個(gè)AudioClip如果只是這樣即使在游戲中只有一次使用也會(huì)導(dǎo)致內(nèi)存消耗過剩,我們應(yīng)該利用Resources.Load()和Resources.UnloadAsset()來保持需要播放的音頻數(shù)據(jù)在內(nèi)存中,一旦它不在需要就立即釋放它。

    5.2.2-Texture


    ? 術(shù)語“Texture” 和“Sprite”新手在游戲開發(fā)中經(jīng)常會(huì)產(chǎn)生困惑,所以值得區(qū)分下,在Unity3d中Texture僅僅是個(gè)圖片,我們習(xí)慣讀作貼圖。本質(zhì)上來講它是一個(gè)大的顏色數(shù)組告訴程序每個(gè)像素是什么顏色。

    ? 而Sprite是一個(gè)2d網(wǎng)格,一個(gè)平對(duì)著當(dāng)前攝像機(jī)的quad,我們習(xí)慣讀作精靈。

    ? 還有一種東西叫做Sprite Sheets,我們稱它為圖集;它用一張大圖包含了很多圖片,最常見的使用時(shí)2d角色動(dòng)畫。這些文件可以用Unity的Sprite Editor工具分割成小圖做幀動(dòng)畫。

    ? 別管這些令人困擾的命名,來簡(jiǎn)單談下Texture:我們導(dǎo)入的這些圖片文件一般都生成于Adobe Photoshop國(guó)內(nèi)基本都是或者一些小眾軟件Gimp等。在運(yùn)行的時(shí)候這些文件被加載到內(nèi)存中,然后Push到GPU,應(yīng)用Shader完成一次Draw Call。一般情況下,渲染一次擁有一個(gè)網(wǎng)格并攜帶一種材質(zhì)的物體便會(huì)使用一次Draw Call,Draw Call的次數(shù)是決定性能比較重要的指標(biāo)。

    ? 壓縮格式

    ? 像音頻文件一樣,Unity為我們多種文件壓縮技術(shù)來更有效的儲(chǔ)存文件。在導(dǎo)入Texture文件時(shí),有幾個(gè)選項(xiàng)我們可以設(shè)置。首先是Texture Type ,這個(gè)設(shè)置不會(huì)影響到文件本身而是說Unity將如何解析,操作和壓縮它。

    ? 在Texture Type為Texture模式下Unity只給我們看到四個(gè)格式選項(xiàng)

    Compressed, 16-bit,True Color和Crunched

    ? 如果我們將Texture Type設(shè)置為Advanced,那么我們就有了更多的設(shè)置選項(xiàng),它給了我們更多的 Texture解析的控制權(quán)。

    ? 紋理的壓縮方式取決于大小和質(zhì)量的平衡,更多的需要做的是了解每種格式來選擇最適合的。但是這里著重要提一下的是Crunched格式,這個(gè)格式壓縮需要很長(zhǎng)時(shí)間,但在運(yùn)行時(shí)減壓是非???。在新版本的Unity中加入了這個(gè)選擇可以看到它被壓縮成PVRTC格式,推薦在開發(fā)手機(jī)應(yīng)用程序時(shí)使用 PVRTC 紋理。你應(yīng)該知道當(dāng)使用 PVRTC 時(shí)與標(biāo)準(zhǔn)JPEG或PNG圖像相比有可能有些圖像質(zhì)量的下降。是否值得在你的程序中做出一些犧牲取決于一些因素,但使用 PVRTC 紋理可以節(jié)省大量的內(nèi)存空間,PVRTC 是個(gè)很好的選擇。

    ? 明智的使用 Mip Maps

    ? 呈現(xiàn)小物件的時(shí)候,像巖石樹木這樣的遠(yuǎn)處物體,一個(gè)高精度的貼圖對(duì)于玩家來說是沒有意義的,因?yàn)榭床坏侥敲炊嗟募?xì)節(jié)。但是如果使用這張高精度的貼圖會(huì)損失原本不應(yīng)該的性能,這時(shí)候需要一個(gè)較少細(xì)節(jié)的紋理來提升程序性能。

    ? Mip Maps的發(fā)明就是來解決這個(gè)問題 的,通過啟用 Generate Mip Maps

    ? 聽著好像很爽的樣子但是他在我們手游中幾乎沒用,啟用Mip Maps還會(huì)讓最后生成的紋理文件增大33%左右。那他存在的意義何在如何什么時(shí)候使用它呢?它唯一有用的地方是攝像機(jī)需要渲染不同距離的紋理時(shí)。如果我們的紋理總是呈現(xiàn)在攝像頭的同樣距離,這時(shí)候開啟Mip Map就一點(diǎn)用都沒只是在浪費(fèi)空間。還有如果只有單一的一種遠(yuǎn)距離物體我們也應(yīng)該禁用它,應(yīng)該從原紋理縮放一個(gè)小紋理給這個(gè)遠(yuǎn)處物體。

    ? **以下時(shí)候應(yīng)該禁用這個(gè)選項(xiàng): **

    • 在2d游戲中的幾乎所有的紋理(2d游戲正交投影不存在近大遠(yuǎn)小)
    • UI界面
    • Mesh貼圖,Sprites,Particle Effects,因?yàn)樗麄兛偸窃跀z像機(jī)差不多的距離渲染不會(huì)有很明顯的距離差

    ? 考慮把圖片打包起來變成圖集

    ? 把圖塊變成圖集之后會(huì)減少Draw Calls的次數(shù)(其實(shí)就是減少M(fèi)aterial 數(shù)量)明顯減少CPU消耗,內(nèi)存消耗上基本相同。一個(gè)圖集下的所有貼圖都應(yīng)該是使用相同Shader的,不然后果很嚴(yán)重做了還不如不做。

    ? 圖集經(jīng)常使用在UI界面,2d游戲中,它在手游中幾乎是必不可少的,因?yàn)镈raw Calls往往會(huì)成為手游的瓶頸。

    ? 我們不應(yīng)該手動(dòng)去生成圖集,有很多現(xiàn)成的工具有Unity自己的有第三方的還有一些源碼工程。要注意圖集不能大于目標(biāo)平臺(tái)的最大要求,圖集最好合理的分布不要為了節(jié)省空間而視圖把圖集塞滿。如果渲染器需要從不同的圖集中調(diào)用紋理會(huì)導(dǎo)致大量的高速緩存命中失敗,從而有引發(fā)內(nèi)存帶寬不足等等問題。 如果做pc游戲的話圖集就沒有特別的必要了,因?yàn)镈raw Calls很少會(huì)成為pc游戲的性能瓶頸。正確的使用圖集它不是僅僅把圖片堆起來。

    ? 對(duì)于通用紋理,盡可能的使用九宮格。如果用大塊的紋理則會(huì)占用較大的內(nèi)存空間。而針對(duì)對(duì)稱紋理則可以使用shader或者Scale翻轉(zhuǎn)等方法來重復(fù)利用以減小內(nèi)存消耗。

    ? **調(diào)整非正方形紋理的壓縮率 **

    ? 不建議導(dǎo)入非正方形或者非2的次冪的紋理到我們的應(yīng)用程序,因?yàn)镚PU往往需要把紋理是變成正方形和2的次冪導(dǎo)致不必要的處理畸形的紋理尺 寸工作量。如果紋理不是2的次冪,Unity會(huì)scale、pad紋理,以使得達(dá)到2的次冪,這樣會(huì)花費(fèi)更多內(nèi)存,讓加載更慢,所以建議是避免導(dǎo)入非正方形和2的次冪的紋理。

    ? Other

    • 通過設(shè)置“MaxSize”來限制圖片的大小,一般來說我們應(yīng)該講圖片縮小到肉眼剛好看不出壓縮的程度。圖片不要超過2048.
    • “Format”則表示壓縮的方式,不同的平臺(tái)我們應(yīng)該用不同的壓縮方式來進(jìn)行壓縮。例如:安卓使用ETC而IOS則使用PVRTC。
    • 一般情況下我們需要關(guān)閉圖片的Read&Write選項(xiàng),否則內(nèi)存會(huì)大一倍。除非我們對(duì)圖像需要進(jìn)行讀寫操作。
    • 針對(duì)顏色范圍不大的素材,我們可以降低圖片的色階以減小圖片的大小。

    5.2.3-模型

    • 保證不可讀寫。
    • 將沒有動(dòng)畫的模型上的動(dòng)畫腳本去除,否則會(huì)消耗cpu。
    • 多個(gè)角色分享一套rig,可以解決資源。
    • 使用MeshCompression
    • 模型莫名期末有很多particle view物體。在3DMAX中當(dāng)你按下6時(shí)候,會(huì)彈出particle view窗口。同時(shí)會(huì)生成一個(gè)多余的particle view物體(這個(gè)物體在大綱中是找不到的,但當(dāng)使用Ctrl+A的時(shí)候,他就會(huì)被選到,而且這個(gè)物體會(huì)占用一定的文件空間),在導(dǎo)出時(shí)particle view會(huì)嚴(yán)重?cái)_亂物體的軸心。決方法很簡(jiǎn)單,只要在max導(dǎo)出之前,按下f11鍵,進(jìn)入max的腳本編輯器,輸入delete $’particle view’,回車,此時(shí)下一行會(huì)提示有幾個(gè)particle view被刪除了。看到這個(gè)數(shù)字即可以放心導(dǎo)出了。
    • 當(dāng)動(dòng)畫播放出現(xiàn)褶皺、破損、奇葩的時(shí)候,估計(jì)是點(diǎn)受骨骼影響太多了,U3D設(shè)置中一個(gè)點(diǎn)最多只能受4個(gè)骨骼影響。
    • 在UI中最好不要使用Mesh特效,否則無法判斷深度。除非使用RendererTexture來適應(yīng),盡可能讓美術(shù)用別的方案來替代。

    5.2.4-文本文件優(yōu)化

    • 解析文本是比較慢的。
    • 將文本轉(zhuǎn)成二進(jìn)制文件,可以有效提高讀寫速度。
    • 將文本分成小塊,只讀取需要的部分。讀入之后如有必要?jiǎng)tCache起來。
    • 利用線程進(jìn)行多線程讀取。

    5.2.5-AssetBundle管理

    目前市面上的大多數(shù)游戲都要涉及到熱更新,從Unity5.0開始,簡(jiǎn)化的API讓AssetBundle的打包似乎不再是一件困難的工作,但是想要管理好AssetBundle的關(guān)系卻并不是那么容易的一件事。

    在游戲中加載資源我使用過兩種做法,都需要自己對(duì)加載方式進(jìn)行封裝,通過多態(tài)來靈活加載工程內(nèi)或者熱更的資源:

  • 一種是講所有需要加載的資源,例如prefab、文本等等放入到Resources下面(盡可能減少資源否則會(huì)影響啟動(dòng)速度),而依賴的資源放在別的文件夾下,熱更的時(shí)候?qū)①Y源加載到沙盒目錄下。在資源加載的時(shí)候,首先對(duì)沙盒目錄進(jìn)行檢查,若有的話,則使用熱更資源,否則就加載Resource下的資源。優(yōu)點(diǎn)是在工程內(nèi)不需要打包,而缺點(diǎn)是由于沒有打包,導(dǎo)致在最后出包的時(shí)候打包緩慢。

  • 而另一種是將所有的資源打成AssetBundle放入StreamingAssets下,熱更的時(shí)候同樣十八AssetBundle下載到沙盒目錄下。資源加載的時(shí)候,首先對(duì)沙盒目錄進(jìn)行檢查,若有的話使用熱更資源,否則就加載StreamingAssets下的資源。在加載的時(shí)候需要提供資源名和包名,在編輯器下可以通過AssetDatabase來直接從編輯器中加載資源,通過將場(chǎng)景加入到BuildSetting中來加載場(chǎng)景,避免每次進(jìn)行修改的時(shí)候都需要重新打AssetBundle。這種方法在最后出包的時(shí)候比較快,在最終確定下資源正確性的時(shí)候構(gòu)建AssetBundle。

    通過延遲加載來對(duì)AssetBundle進(jìn)行加載,在一般的使用場(chǎng)景下,我們并不需要將所有的AssetBundle進(jìn)行載入。在游戲中,我們將建立一張常用的Bundle列表,用于進(jìn)入場(chǎng)景時(shí)加載該場(chǎng)景中的常駐資源。而不一定會(huì)出現(xiàn)的資源則在需要的時(shí)候進(jìn)行即時(shí)加載,并且放入Bundle池中隨時(shí)準(zhǔn)備取用,當(dāng)Bundle閑置達(dá)到一定的時(shí)間后對(duì)其進(jìn)行自動(dòng)的卸載,這取決于該Bundle的使用頻度。在切換場(chǎng)景之后卸載該場(chǎng)景的常用Bundle而去加載另一個(gè)場(chǎng)景的常用Bundle。

    要注意Bundle的細(xì)粒度,如果Bundle的細(xì)粒度超過一定數(shù)量的話必然會(huì)引起熱更包體積過大,玩家的更新需要下載更多的資源包,而在場(chǎng)景中也需要加載更多原本并不被需要的資源,而過小細(xì)粒度則會(huì)造成場(chǎng)景加載的緩慢,給管理上也會(huì)增加難度。所以適當(dāng)?shù)募?xì)粒度在AssetBundle的分包中也非常重要。

    將公用的資源單獨(dú)打成包:如果一個(gè)資源本身沒有標(biāo)記任何的Bundle包,而被許多別的Bundle包引用則會(huì)被打入每一個(gè)引用它的Bundle中,造成包體積的膨脹。例如Shader這樣的材質(zhì)就很有必要單獨(dú)打成一個(gè)包用作公用,否則包體積和游戲內(nèi)存占用會(huì)變成一個(gè)大問題。

    當(dāng)手機(jī)的容量較小時(shí),可以通過WWW.LoadFromCacheOrDownload來進(jìn)行加載,而不必?fù)?dān)心內(nèi)存不足的問題。

    在將代碼打包到Prefab的時(shí)候?qū)τ贑omponent要用動(dòng)態(tài)加載的方式,考慮使用lua腳本進(jìn)行操作,或者是直接動(dòng)態(tài)從程序集加載,這樣可以避免資源與代碼不同步的情況發(fā)生。可以只對(duì)代碼進(jìn)行修改而不需要重新進(jìn)行資源打包。

    在使用第二種方案建立項(xiàng)目的時(shí)候可以建立一個(gè)或者幾個(gè)資源項(xiàng)目,用于大量資源的打包,用于將AssetBundle打包并放入主項(xiàng)目中,在主項(xiàng)目的在打包的時(shí)候不必再對(duì)所有的AssetBundle資源進(jìn)行再打包,可以大大提高打包效率,并且可以將工作流放入到資源項(xiàng)目當(dāng)中,提高資源的迭代效率。

    在為資源分包的時(shí)候可以按照文件夾來進(jìn)行區(qū)分,以便于管理。

    當(dāng)在一個(gè)地方需要用到包中的一小個(gè)資源,例如一個(gè)2048*2048圖集中的一個(gè)小icon。拷貝一份,并且放入到目前需要使用的包中,避免由于小的資源需求而引入大內(nèi)存消耗。

  • 5.2.6-資源工作流管理

    作為程序,我們?cè)谫Y源上面花的精力自然是越少越好,但是如果沒有好的工具鏈,好的流程,我們必定將會(huì)困在永遠(yuǎn)做不完的資源管理中。美術(shù)發(fā)過來的max文件或許需要經(jīng)過你的導(dǎo)出、導(dǎo)入到Unity、拖成預(yù)制體、掛動(dòng)畫、掛碰撞盒等等的操作之后才能成為一個(gè)真正可用的資源。這個(gè)時(shí)候一個(gè)好的工具顯得格外重要。

    • uTomate,用于管理流程的Unity插件,我們可以通過簡(jiǎn)單的節(jié)點(diǎn)連接來對(duì)我們的資源進(jìn)行一系列操作的配置。除此之外,我們還可以用它來做一鍵打包等功能。
    • Defaulter – Custom Importer Defaults ,用于管理資源的導(dǎo)入統(tǒng)一化,通過路徑來決定其中資源的格式,例如:貼圖對(duì)應(yīng)著的MaxSize、Format、Read&Write等等,還支持其他很多的資源,通過這個(gè)我們不再需要對(duì)每一個(gè)導(dǎo)入的資源進(jìn)行手動(dòng)的設(shè)置了,由于其開源的有點(diǎn),我們也可以根據(jù)我們自己的需要進(jìn)行優(yōu)化。由于作者不再維護(hù)了,所以我們或許需要自己來進(jìn)行編寫。
    • 熟悉一些簡(jiǎn)單的程序腳本,例如maxscript或者是ps中的ExtendScript ToolkitCS6。我就曾經(jīng)自己寫過一個(gè)自動(dòng)切圖的小插件,不過效率不是很行,但是語言本身并不難學(xué),能給美術(shù)和程序自己帶來很多方便,通過C#對(duì)命令行調(diào)用的方式集成到Unity中,相信整個(gè)工作會(huì)輕松不少。
    • 利用Jenkins或者Hudson進(jìn)行持續(xù)集成。人肉集成是對(duì)人力與資源的一種浪費(fèi),極其容易出現(xiàn)錯(cuò)誤,而本地打包則大大占用了程序員的本地帶寬,讓程序員無法繼續(xù)進(jìn)行工。而通過配置Jenkins來自動(dòng)實(shí)現(xiàn)可參數(shù)化的、穩(wěn)健的、可持續(xù)的集成,項(xiàng)目組可以集中更多的力量來進(jìn)行產(chǎn)品的迭代。
    • 使用Spine或者Unity Anima2D來制作2D動(dòng)畫,可以事倍功半。
    • 當(dāng)然最靠譜的還是自己用C#來寫工具,雖然會(huì)花一些時(shí)間,但是磨刀不誤砍柴工,花一天時(shí)間寫工具,今后的幾個(gè)月當(dāng)中可能會(huì)減少你好幾天的工作量。好工具所帶來的生產(chǎn)力可能大大超出你的想象。
      資源的工作流除了用于生成資源,對(duì)于資源的管理也是非常的重要。

    5.3-Unity相機(jī)優(yōu)化

    5.3.1-Occlusion Culling遮擋剔除

    unity 中的剔除包括兩種,一種是視角剔除,凡是不在攝像機(jī)視野內(nèi)的物體,不進(jìn)行渲染,第二種就是遮擋剔除,被擋住的物體不被渲染,即使它在相機(jī)視野內(nèi),兩種方法可以共存

    不進(jìn)行視角剔除,也不進(jìn)行遮擋剔除

    只進(jìn)行視角剔除

    二者都進(jìn)行

    Occlusion Culling使用兩種存儲(chǔ)方式, 一個(gè)為 View Cells (靜態(tài)物體) 另一種為Target Cells (移動(dòng)的物體).二者的數(shù)據(jù)分別單獨(dú)存儲(chǔ)

    較大的物體不易當(dāng)被遮擋物,較小的物體不易當(dāng)遮擋物

    可以通過‘overdraw’來觀看場(chǎng)景中的遮擋情況,注意該模式下視野就代表攝像機(jī),

    注意:黃色的區(qū)域?yàn)檎趽跆蕹齾^(qū)域,只有在這個(gè)區(qū)域內(nèi),遮擋剔除效果才會(huì)顯現(xiàn)

    一.Occlusion Culling Window

    在 Window > Rendering打開Occlusion Culling Window

    Object菜單欄:scene Filter:文件過濾器,all 就是顯示場(chǎng)景中所有的物體,renderers 顯示場(chǎng)景中帶有render組建的物體,occlusion Areas 顯示場(chǎng)景中帶有occlusion Area組件的物體

    選中一個(gè)物體后,也可以在這個(gè)面板設(shè)置它的Occluder Static和Oculudee Static

    NOTE: Whenever your camera is outside occlusion areas, occlusion culling will not be applied. It is important to set up your Occlusion Areas to cover the places where the camera can potentially be, but making the areas too large incurs a cost during baking.

    當(dāng)你的相機(jī)在遮擋區(qū)域之外時(shí),遮擋剔除將不被應(yīng)用。設(shè)置遮擋區(qū)域以覆蓋相機(jī)可能出現(xiàn)的位置是很重要的,但是在烘焙過程中,使遮擋區(qū)域過大會(huì)帶來成本。

    當(dāng)使用l (LOD) 時(shí). (LOD0) 作為 Occluder.也就是說如果當(dāng)前時(shí)Lod1則不會(huì)發(fā)生遮擋

    Smallest Occluder:遮擋物的最小體積,小于這個(gè)數(shù)則不會(huì)遮擋其他物體

    Smallest Hole:有的墻上有縫隙,你可以通過這個(gè)縫隙看到后面的物體,這個(gè)值是縫隙的直徑

    Backface Threshold:背面閾值,有些背面你是不可以到達(dá)的,比如說地形的下面,一個(gè)封閉房間的外面,這些地方你始終看不了,但是烘焙之后這些數(shù)據(jù)是包含在unity里面的,100代表不剔除這些數(shù)據(jù),值越小數(shù)據(jù)就會(huì)越小,只是剔除背面數(shù)據(jù)

    Clear:清除烘焙數(shù)據(jù) Bake:烘焙數(shù)據(jù)

    二.Occlusion Area

    Occlusion Area 遮擋區(qū)域:應(yīng)用于遮擋剔除移動(dòng)的物體. (移動(dòng)的物體不能設(shè)置為 static). 你可以在一個(gè)空物體上面添加組件 Occlusion Area (Component -> Rendering -> Occlusion Area ).

    添加Occlusion Area組件之后, 點(diǎn)擊 Is View Volume 檢測(cè)遮擋移動(dòng)的物體

    Size:遮擋區(qū)域的大小

    Center:遮擋區(qū)域的位置

    Is View Volume:是否應(yīng)用遮擋剔除移動(dòng)的物體

    遮擋區(qū)域可以有多個(gè)

    在該區(qū)域內(nèi)的物體,可以移動(dòng),不用設(shè)置靜態(tài),只要被遮擋就不會(huì)渲染,不被遮擋就渲染,事先也得烘焙

    5.3.2-Frustum Culling視錐體剔除

    一.應(yīng)用背景

    在現(xiàn)代游戲中,游戲資源越來越多,游戲場(chǎng)景也越來越大越來越復(fù)雜,雖說硬件設(shè)備更新迭代很快,性能也日漸強(qiáng)大,但這還遠(yuǎn)不能緩解復(fù)雜繁多的資源帶來的性能壓力,因而性能優(yōu)化仍然很有必要。場(chǎng)景資源的剔除是性能優(yōu)化的一個(gè)重要方面,剔除方式也有很多,比如OcclusionCulling、Frustum Culling、layerCullingDistance等。由于項(xiàng)目的需要,這里重點(diǎn)關(guān)注Frustum Culling(視錐體剔除)。

    視錐體剔除的基本思想:判斷對(duì)象是否在相機(jī)視錐體內(nèi)(相交也算),在則不剔除,不在則剔除。判斷的方法也有很多,比較常見的方法是判斷對(duì)象的BoundingBox與相機(jī)視錐體的六個(gè)剪裁平面的關(guān)系,來判斷對(duì)象是否在視錐體中。為此Unity也提供了原生API以支持基于視錐體的剔除方案。

    二.問題要點(diǎn)

    這里基于Unity提供的原生API來探討基于視錐體的剔除流程,需要使用到GeometryUtility中提供的API。

    1.獲取相機(jī)的剪裁平面:

    有多個(gè)API可獲得剪裁平面:

    ①public static Plane[] CalculateFrustumPlanes(Camera camera);

    ② public static Plane[] CalculateFrustumPlanes(Matrix4x4 worldToProjectionMatrix);

    ③ public static void CalculateFrustumPlanes(Camera camera, Plane[] planes);

    ④ public static void CalculateFrustumPlanes(Matrix4x4 worldToProjectionMatrix, Plane[] planes);

    前三個(gè)API最終都是調(diào)用了④來實(shí)現(xiàn)剪裁面獲取功能的,其中①和②由于在內(nèi)部創(chuàng)建了Plane數(shù)組,并返回,因此存在GC,而③和④需要預(yù)先定義一個(gè)長(zhǎng)度為6的Plane數(shù)組,并傳入方法,方法內(nèi)部會(huì)修改這些對(duì)象的值,因而不存在GC。所以建議使用③或者④。

    通過上述API獲取的剪裁平面的順序依次是:左、右、下、上、近、遠(yuǎn)。

    2.傳入需要檢測(cè)對(duì)象的BondingBox:

    public static bool TestPlanesAABB(Plane[] planes, Bounds bounds);

    調(diào)用上述API,傳入通過①獲取的剪裁平面及對(duì)象的BoundingBox即可檢測(cè)出該對(duì)象是否在視錐體內(nèi)。

    三.Demo源碼

    using System.Collections.Generic; using UnityEditor; using UnityEngine; using System.Linq;public class FrustumTest : MonoBehaviour {public Camera CulingCamera;public Renderer[] CullingTestObjects;private Plane[] planes;void OnEnable(){planes = new Plane[6];}void Update(){GeometryUtility.CalculateFrustumPlanes(CulingCamera, planes);for (var index = 0; index < CullingTestObjects.Length; index++){var bounds = CullingTestObjects[index].bounds;var result = GeometryUtility.TestPlanesAABB(planes, bounds);CullingTestObjects[index].enabled = result;}}[MenuItem("Test/Create")]static void Create(){var gos = new List<GameObject>();var root = new GameObject("Root").transform;for (var i = 0; i < 10; i++){for (var j = 0; j < 10; j++){for (var k = 0; k < 10; k++){var go = GameObject.CreatePrimitive(PrimitiveType.Cube);go.transform.position = new Vector3(i, j, k) * 2;go.transform.parent = root;gos.Add(go);}}}var test = new GameObject("FrustumTest").AddComponent<FrustumTest>();test.CulingCamera = Camera.main;test.CullingTestObjects = gos.Select(item => item.GetComponent<Renderer>()).ToArray();} }

    四.實(shí)驗(yàn)效果

    五.存在的問題:

    通過上述API獲取剪裁面時(shí),只能一次性獲所有的剪裁面,而在一些特殊情況下我們往往只需要部分剪裁面即可。同時(shí)上述API底層采用了P/Invoke方式調(diào)用了非托管C++庫來實(shí)現(xiàn)剪裁面的計(jì)算,頻繁調(diào)用會(huì)有一定的性能損耗。為了實(shí)現(xiàn)更加個(gè)性化的基于視錐體的裁剪方案,我們往往需要自行計(jì)算剪裁面,并進(jìn)行包含檢測(cè)。

    5.4-UnityUGUI優(yōu)化

    1.UGUI中若不需要使用到RaycastTarget的,務(wù)必將其關(guān)閉,一般UI里也就是按鈕才需要接收響應(yīng)事件,那么大部分image和text是是不需要開RaycastTarget的。

    但是問題就來了,Unity默認(rèn)在hierarchy窗口Create->UI->Image 、Text的時(shí)候就會(huì)自動(dòng)幫我們勾選上RaycastTarget, 一個(gè)復(fù)雜點(diǎn)的界面至少也300+個(gè)Image和Text, 總不能一個(gè)個(gè)取消吧。 所以我們可以重寫Create->UI->Image的事件。

    [MenuItem("GameObject/UI/Image")]static void CreatImage(){if(Selection.activeTransform){if(Selection.activeTransform.GetComponentInParent<Canvas>()){GameObject go = new GameObject("image",typeof(Image));go.GetComponent<Image>().raycastTarget = false;go.transform.SetParent(Selection.activeTransform);}}}

    2.禁用空的Image。在Unity項(xiàng)目中,有時(shí)候會(huì)用空的Image并將alpha設(shè)置為0來接收點(diǎn)擊事件。這樣會(huì)產(chǎn)生不必要的overdraw,增加性能負(fù)擔(dān),可以使用以下腳本,只監(jiān)聽事件,不畫網(wǎng)格,從而減少overdraw。

    using UnityEngine.UI;public class EmptyRaycast : Graphic {public override void SetMaterialDirty(){}public override void SetVerticesDirty(){}protected override void OnPopulateMesh(VertexHelper vh){vh.Clear();} }

    按如下使用方式,可以實(shí)現(xiàn)點(diǎn)擊事件的監(jiān)聽,并且不產(chǎn)生overdraw。

    而如果是使用Image的話,則會(huì)產(chǎn)生overdraw。

    3.場(chǎng)景中應(yīng)盡量保持少許的Canvas,新增一個(gè)Canvas,都會(huì)增加一個(gè)Batches.

    4.UI 上的的Color屬性 不建議直接修改,修改會(huì)導(dǎo)致重繪mesh,建議修改材質(zhì)球顏色不會(huì)出現(xiàn)這個(gè)問題

    5.在Loading界面使用動(dòng)態(tài)打圖集技術(shù) 可以很大的優(yōu)化DC。但是動(dòng)態(tài)打圖集很增加Loading時(shí)間。

    6.設(shè)置UI點(diǎn)擊其他區(qū)域退出當(dāng)前UI這樣的類似功能 會(huì)產(chǎn)生大量Overdraw,最好的方法寫個(gè)代碼 繼承Image 重新 OnPopulateMesh 方法,只寫一行 tofill.clear(); 就搞定了

    7.Sprite導(dǎo)入 UI一般關(guān)閉 Read/Write 和 Generate MipMaps

    8.GameObject.SetActive 盡量少使用。因?yàn)樵贠nEnable 和OnDisenable 都會(huì)重新設(shè)置一遍所有的臟標(biāo)志. 尤其不要對(duì)大量的 text 進(jìn)行 setactive。單個(gè)UI建議使用 canvas renderer的.cull屬性。如果多個(gè)UI建議使用canvas group中的alpha 設(shè)置0。

    9.避免使用Camera.main

    當(dāng)設(shè)置畫布進(jìn)行渲染時(shí),不管該畫布是在世界空間還是攝像機(jī)的屏幕空間,都可以指定用于為UI中Graphic Raycaster生成交互事件的攝像機(jī)。渲染模式為“Screen Space - Camera”的畫布需要使用該設(shè)置,該設(shè)置名為“Render Camera”。

    然而在渲染模式為“World Space”的畫布上,該設(shè)置是可選的,名為“Event Camera”。

    如果將世界空間畫布的Event Camera字段留空,這不意味著該畫布不會(huì)接收事件。它會(huì)使用游戲的主攝像機(jī)。為了確定哪個(gè)攝像機(jī)是主攝像機(jī),該畫布會(huì)訪問Camera.main屬性。

    根據(jù)Unity所使用的代碼路徑,每幀中每有一個(gè)Graphic Raycaster和世界空間畫布,該畫布會(huì)訪問7到10次Camera.main。每次訪問Camera.main都會(huì)調(diào)用Object.FindObjectWithTag。這個(gè)做法在運(yùn)行時(shí)并不合適。

    解決方案:避免使用Camera.main

    緩存攝像機(jī)的引用,然后創(chuàng)建系統(tǒng)來跟蹤主攝像機(jī)。如果使用世界空間畫布,要指定Event Camera,不要將該屬性留空。如果需要修改Event Camera,編寫代碼來更新Event Camera屬性。

    10.避免使用布局分組

    問題:每個(gè)影響布局的UI元素都會(huì)至少執(zhí)行一次GetComponents調(diào)用。

    當(dāng)修改布局系統(tǒng)的一個(gè)或多個(gè)子元素時(shí),會(huì)使布局變臟。修改后的子元素會(huì)使擁有該元素的布局系統(tǒng)(Layout System)無效化。

    簡(jiǎn)單介紹一下布局系統(tǒng):布局系統(tǒng)是一組連續(xù)的布局分組(Layout Group),它們?cè)诓季衷?#xff08;Layout Element)之上。布局元素不只是名為L(zhǎng)ayout Element的組件,它們還包括UI圖像、文字和Scroll Rect組件,而且Scroll Rect同時(shí)也是布局分組。

    回到問題本身,每個(gè)使布局變臟的UI元素都會(huì)至少執(zhí)行一次GetComponents調(diào)用,該調(diào)用會(huì)在布局元素父對(duì)象上尋找有效的布局分組。找到有效布局分組后,它會(huì)繼續(xù)遍歷Transform層級(jí),直到停止尋找分組或是到達(dá)層級(jí)的根部分,無論先滿足哪個(gè)條件都會(huì)停止尋找過程。因此。每個(gè)布局分組會(huì)給每個(gè)子布局元素的改變過程添加一次GetComponents調(diào)用,使嵌套布局分組的性能變差。

    解決方案:避免使用布局分組。

    使用錨點(diǎn)進(jìn)行比例布局。在擁有動(dòng)態(tài)元素?cái)?shù)量的活躍UI上,考慮編寫代碼來計(jì)算布局,僅在需要時(shí)運(yùn)行該代碼,而不是每次發(fā)生改變的時(shí)候。

    11.Other
    動(dòng)態(tài)打圖集算法

    Github: unityRuntimeSpriteSheetsGenerator

    圖片壓縮格式選擇

    • 安卓主要用RGB ETC 4bit 不支持A通道,如果透明 用ETC2 8bit 或者 再用一張ETC 1通道
    • Crunched 是untiy的二次壓縮方式,缺點(diǎn)就是壓縮時(shí)間過久
    • IOS主要用 RGBAPVRTC4 其次選用 SATC
    • 大部分壓縮格式要求 寬高是2的整數(shù)次冪(POT) 或4的整數(shù)倍數(shù) .如果不能滿足,就單獨(dú)打圖集
    • 安卓 RGB ETC4通道分離 split alpha channel。要注意在Project setting中g(shù)raphics shader 中添加 DefaultETC1。否則在真機(jī)可能出錯(cuò) ?;蛑苯佑肊TC2(優(yōu)先選擇)

    打圖集的規(guī)則

    • 盡量把同一個(gè)界面放在一個(gè)圖集
    • 盡量不要把同一個(gè)圖放在多個(gè)公用圖集
    • 使用頻率高的圖 放在一個(gè)圖集
    • 大圖UI盡量不打進(jìn)圖集
    • 建議使用插件打包圖集,效果會(huì)略微比Unity自帶的圖集打包好一點(diǎn)。節(jié)省空間很大一點(diǎn)

    UI 合批流程

    • 遍歷UI
    • 合批測(cè)試(當(dāng)前UI會(huì)判斷底下UI是否可以合批 如果不合批 深度底下最大的+1)
    • 判斷順序 如果深度一樣 然后判斷材質(zhì)是否一樣 再判斷 圖片是否一樣 最后再根據(jù)面板順序排序,如果深度為-1 則不渲染
    • 得出排序數(shù)組 看相鄰元素是否一樣 然后合批

    會(huì)打斷合批的操作

    父物體 的 Pos 改變z軸 , 旋轉(zhuǎn)改變 x y 軸,會(huì)退出批處理 會(huì)打斷上下合批(UI和其他UI不在同一平面就不能合批)

    UI 網(wǎng)格重建流程

    某ui改變----將此UI設(shè)置臟標(biāo)志—添加臟標(biāo)志隊(duì)列–下一幀重建mesh

    5.5-C# 語言層面的優(yōu)化

    主要思想是減少存的動(dòng)態(tài)分配和釋放,以及內(nèi)存泄露,減少垃圾回收。

    1:
    (1)字符串的處理 使用stringbuild 類代替string 進(jìn)行多個(gè)字符串的拼接。
    (2)String.format();
    避免使用“+”“aaa”+“bbb”這種方式 原因是“+”對(duì)字符串進(jìn)行拼接,會(huì)導(dǎo)致臨時(shí)
    堆string 對(duì)象發(fā)生頻繁的堆對(duì)象的分配和釋放。

    2.盡可能使用for循環(huán)代替foreach
    數(shù)組 泛型list<> 一律使用for ,字典使用foreach
    原因: 每次foreach產(chǎn)生一個(gè)臨時(shí)的迭代器對(duì)象,迭代器會(huì)額外的分配內(nèi)存。

    3:頻繁調(diào)用的函數(shù)中,如果有臨時(shí)變量是引用類型,要將其改為成員變量。避免頻繁的堆對(duì)象的創(chuàng)建和釋放。

    4:如果函數(shù)運(yùn)行需要一個(gè)List 需要設(shè)置List為成員變量 獨(dú)立與函數(shù)的運(yùn)行,可以
    通過clear()函數(shù)清空,重復(fù)使用全局成員集合,清空函數(shù)不會(huì)刪除內(nèi)存空間,大大的減輕性能的負(fù)擔(dān)。

    5:避免使用Lambda表達(dá)式,存在內(nèi)存泄露的內(nèi)存隱患。

    6:盡量使用對(duì)象池 避免對(duì)象的頻繁創(chuàng)建和釋放,導(dǎo)致大量無效內(nèi)存的積累,引發(fā)GC(垃圾回收)操作,造成性能的降低

    7:避免裝箱和拆箱的操作,會(huì)導(dǎo)致堆內(nèi)存的分配。

    8:避免使用AraayList會(huì)把所有插入的數(shù)據(jù)當(dāng)作object類處理,存在一個(gè)裝箱的過程。盡量使用泛型List<>;

    9:避免使用反射機(jī)制,運(yùn)行時(shí)獲取類型信息,性能低下。

    10:即時(shí)的將對(duì)象設(shè)置為null、 委托事件即時(shí)注銷。

    11.別把成員變量聲明為 public 或 protected。都聲明為 private 而使用 public/protected 的屬性

    12.不在代碼中使用具體的路徑和驅(qū)動(dòng)器名。 使用相對(duì)路徑,并使路徑可編程。

    13.避免不必要的調(diào)用 ToUpper 或 ToLower 方法
    String是不變類,調(diào)用ToUpper或ToLower方法都會(huì)導(dǎo)致創(chuàng)建一個(gè)新的字符串。如果被頻繁調(diào)用,將導(dǎo)致頻繁創(chuàng)建字符串對(duì)象。這違背了“避免頻繁創(chuàng)建對(duì)象”這一基本原則。
    例如,bool.Parse方法本身已經(jīng)是忽略大小寫的,調(diào)用時(shí)不要調(diào)用ToLower方法。
    另一個(gè)非常普遍的場(chǎng)景是字符串比較。高效的做法是使用 Compare 方法,這個(gè)方法可以做大小寫忽略的比較,并且不會(huì)創(chuàng)建新字符串。
    還有一種情況是使用 HashTable 的時(shí)候,有時(shí)候無法保證傳遞 key 的大小寫是否符合預(yù)期,往往會(huì)把 key 強(qiáng)制轉(zhuǎn)換到大寫或小寫方法。實(shí)際上 HashTable 有不同的構(gòu)造形式,完全支持采用忽略大小寫的 key: new HashTable(StringComparer.OrdinalIgnoreCase)。

    14…絕對(duì)不要在循環(huán)中使用try-Catch.

    15.利用using和try/finally語句來清理資源

    16.盡量少用模運(yùn)算和除法運(yùn)算,比如a/5f,一定要寫成a*0.2f。

    17.不要濫用靜態(tài)對(duì)象:由于靜態(tài)對(duì)象始終存在于內(nèi)存當(dāng)中,過度濫用的話容易出現(xiàn)占用內(nèi)存過多的情況。當(dāng)不再需要的時(shí)候,將靜態(tài)大對(duì)象置空,保證GC能夠正常進(jìn)行。

    18.使用尾遞歸而非其他的遞歸,尾遞歸的性能好于頭遞歸。

    5.6-圖形渲染層面

    1.不要使用實(shí)時(shí)陰影,使用陰影紋理或者簡(jiǎn)單的圖片模擬陰影。

    2.減少頂點(diǎn),減少三角面數(shù),峰值小于10w面/每幀,使用LOD進(jìn)行多層次模型設(shè)置,進(jìn)行遮擋。

    3.減少Drawcall 峰值<200 對(duì)場(chǎng)景物件 比如說:石頭,樹木等使用相同材質(zhì)相同貼圖的物體進(jìn)行批處理,降低DC。人物模型(人物模型一般都是帶骨骼的)SkinMesh。即便使用相同的材質(zhì)貼圖,DC也不能進(jìn)行批處理。使用Lightmap技術(shù)降低DC。 UI圖素進(jìn)行合并(打包圖集)降低DC。

    4.盡量使用簡(jiǎn)單材質(zhì),適合移動(dòng)平臺(tái)(手機(jī))Mobile這種Shader或者使用自定義一些優(yōu)化過的Shader,高級(jí)Shader嚴(yán)重降低幀率,加大能耗,或者不可用。

    5.在紋理和質(zhì)量之間做平衡,在保證質(zhì)量不受太大影響的情況下,盡量使用小尺寸的紋理,提升效率。減少安裝包的大小,九宮格等

    6.減少骨骼數(shù)量的使用15個(gè)上下左右,減少粒子系統(tǒng),粒子的數(shù)量。盡量減少粒子數(shù)量。

    7.共享材質(zhì) 多一個(gè)材質(zhì)DC就會(huì)上升 使用共享材質(zhì) 將多張貼圖畫在一張較大的貼圖上面,達(dá)到共享材質(zhì)的作用。

    8.減少,水面折射效果,或者霧效果。

    9.嘗試使用遮擋剔除Occlusion Culling進(jìn)行渲染上面優(yōu)化。

    10.使用LOD技術(shù),在LOD2和LOD1可以修改貼圖的品質(zhì),Cast Shadow和 ReceiveShadow可以移除

    11.能不使用實(shí)時(shí)光渲染則盡量不要使用實(shí)時(shí)光渲染,使用光照貼圖(LightMap)替代

    12.將場(chǎng)景中的靜態(tài)物體進(jìn)行合并Mesh處理

    13.場(chǎng)景中如果沒有使用燈光和像素?zé)?#xff0c;就不要使用法線貼圖,因?yàn)榉ň€效果只有在有光源(Direct Light/Point Light/Angle Light/Pixel Light)的情況下才有效果。

    14.如果硬陰影可以解決問題就不要用軟陰影,并且使用不影響效果的低分辨率陰影;

    6-Unity3D性能優(yōu)化——工具篇

    6.1-游戲性能簡(jiǎn)述

    提起游戲性能,首先要提到的就是,不僅開發(fā)人員,所有游戲玩家都應(yīng)該會(huì)接觸到的一個(gè)名詞:幀率(Frame rate)。

    幀率是衡量游戲性能的基本指標(biāo)。在游戲中,“一幀”便是繪制到屏幕上的一個(gè)靜止畫面。繪制一幀到屏幕上也叫做渲染一幀。每秒的幀數(shù)(fps)或者說幀率表示GPU處理時(shí)每秒鐘能夠更新的次數(shù)。高的幀率可以得到更流暢、更逼真的動(dòng)畫。

    現(xiàn)階段大多數(shù)游戲的理想幀率是60FPS,其帶來的交互感和真實(shí)感會(huì)更加強(qiáng)烈。通常來說,幀率在30FPS以上都是可以接受的,特別是對(duì)于不需要快速反應(yīng)互動(dòng)的游戲,例如休閑、解密、冒險(xiǎn)類游戲等。有些項(xiàng)目有特殊的需求,比如VR游戲,至少需要90FPS。當(dāng)幀率降低到30FPS以下時(shí),玩家通常會(huì)有不好的體驗(yàn)。

    而現(xiàn)階段隨著支持144HZ刷新率的硬件設(shè)備的涌現(xiàn),能否維持對(duì)應(yīng)高幀率又是一項(xiàng)新的指標(biāo),尤其是在電競(jìng)領(lǐng)域

    但在游戲中重要的不僅僅幀率的速度,幀率同時(shí)也必須非常穩(wěn)定。玩家通常對(duì)幀率的變化比較敏感,不穩(wěn)定的幀率通常會(huì)比低一些但是很穩(wěn)定的幀率表現(xiàn)更差。

    雖然幀率是一個(gè)我們談?wù)撚螒蛐阅艿幕緲?biāo)準(zhǔn),但是當(dāng)我們提升游戲性能時(shí),更因該想到的是渲染一幀需要多少毫秒。幀率的相對(duì)改變?cè)诓煌秶鷷?huì)有不同的變化。比如,從60到50FPS呈現(xiàn)出的是額外3.3毫秒的運(yùn)行時(shí)間,但是從30到20FPS呈現(xiàn)出的是額外的16.6毫秒的運(yùn)行時(shí)間。在這里,同樣降低了10FPS,但是渲染一幀上時(shí)間的差別是很顯著的。

    我們還需要了解渲染一幀需要多少毫秒才能滿足當(dāng)前幀率。通過公式 1000/(想要達(dá)到的幀率)。通過這個(gè)公式可以得到,30FPS必須在33.3毫秒之內(nèi)渲染完一幀,60FPS必須在16.6毫秒內(nèi)渲染完一幀。

    渲染一幀,Unity需要執(zhí)行很多任務(wù)。比如,Unity需要更新游戲的狀態(tài)。有一些任務(wù)在每一幀都需要執(zhí)行,包括執(zhí)行腳本,運(yùn)行光照計(jì)算等。除此之外,有許多操作是在一幀執(zhí)行多次的,例如物理運(yùn)算。當(dāng)所有這些任務(wù)都執(zhí)行的足夠快時(shí),我們的游戲才會(huì)有穩(wěn)定且理想的幀率。當(dāng)這些任務(wù)執(zhí)行不滿足需求時(shí),渲染一幀將花費(fèi)更多的時(shí)間,并且?guī)蕰?huì)因此下降。

    知道哪些任務(wù)花費(fèi)了過多的時(shí)間,是游戲性能問題的關(guān)鍵。一旦我們知道了哪些任務(wù)降低了幀率,便可以嘗試優(yōu)化游戲的這一部分。這就是為什么性能分析工具是游戲優(yōu)化的重點(diǎn)之一。

    6.2-Unity3d性能分析工具

    工欲善其事必先利其器,這里我們來講解Unity3D優(yōu)化所需的工具

    如果游戲存在性能問題,游戲運(yùn)行就會(huì)出現(xiàn)緩慢、卡頓、掉幀甚至直接閃退等現(xiàn)象。在我們嘗試解決問題前,需要先知道其問題的起因,而嘗試不同的解決方案。若僅靠猜測(cè)或者依據(jù)自身原有的經(jīng)驗(yàn)去解決問題,那我們可能會(huì)做無用功,甚至引申出更復(fù)雜的問題。

    在這些時(shí)候我們就需要用到性能分析工具,性能分析工具主要測(cè)試游戲運(yùn)行時(shí)各個(gè)方面性能,如CPU、GPU、內(nèi)存等。通過性能分析工具,我們能夠透過游戲運(yùn)行的外在表現(xiàn),獲取內(nèi)在信息,而這些信息便是我們鎖定引起性能問題的關(guān)鍵所在。

    在我們進(jìn)行Unity性能優(yōu)化的過程中,最主要用的到性能分析工具包括,Unity自帶的Unity Profile,IOS端的XCode ,以及一些第三方插件,如騰訊推出的UPA性能分析工具。

    我們主要針對(duì)Unity Profile進(jìn)行講解,之后也會(huì)略微介紹另外一些性能分析工具。

    6.2.1-Unity Profile

    Unity Profile是Unity中最常用的官方性能分析工具,在使用Unity開發(fā)游戲的過程中,借助Profiler來分析CPU、GPU及內(nèi)存使用狀況是至關(guān)重要的。

    首先我們來了解Unity Profile的面板:
    我們通過Window——>Profiler來激活Unity Profile面板

    在下圖中我們可以看到Unity Profile面板,其中有很多profilers,每個(gè)profiler顯示我們當(dāng)前項(xiàng)目一個(gè)方面的信息,如CPU、GPU、渲染(Rendering)、內(nèi)存(Memory)、聲音(Audio)、視屏(Video)、物理(Physics)、ui及全局光照(global illumination)。

    當(dāng)項(xiàng)目運(yùn)行時(shí),每個(gè)profilers會(huì)隨著運(yùn)行時(shí)間來顯示數(shù)據(jù),有些性能問題是持續(xù)性的,有些僅在某一幀中出現(xiàn),還有些性能問題可能會(huì)隨時(shí)間推移而逐漸顯出出來。

    在面板的下半部分顯示了我們選中的profilers當(dāng)前幀的詳細(xì)內(nèi)容,我們可以通過選擇列標(biāo)題,通過這一列的信息值來排序。
    在CPU usage profiler中的列表題分別為:
    Total:當(dāng)前任務(wù)的時(shí)間消耗占當(dāng)前幀cpu消耗的時(shí)間比例。
    Self:任務(wù)自身時(shí)間消耗占當(dāng)前幀cpu消耗的時(shí)間比例。
    Calls:當(dāng)前任務(wù)在當(dāng)前幀內(nèi)被調(diào)用的次數(shù)。
    GC Alloc:當(dāng)前任務(wù)在當(dāng)前幀內(nèi)進(jìn)行過內(nèi)存回收和分配的次數(shù)。
    Time ms:當(dāng)前任務(wù)在當(dāng)前幀內(nèi)的耗時(shí)總時(shí)間。
    Self ms:當(dāng)前任務(wù)自身(不包含內(nèi)部的子任務(wù))時(shí)間消耗。

    當(dāng)我們?cè)趯蛹?jí)視圖中點(diǎn)擊函數(shù)名字時(shí),CPU usage profiler將在Profiler窗口上部的圖形視圖中高亮顯示這個(gè)函數(shù)的信息。比如我們選中Cameta.Render,Rendering的信息就會(huì)被高亮顯示出來。

    我們可以Profiler的左下的下拉菜單中選擇Timeline。

    Timeline顯示了兩件事:cpu任務(wù)的執(zhí)行順序和哪個(gè)線程負(fù)責(zé)什么任務(wù)。線程允許不同的任務(wù)同時(shí)執(zhí)行。當(dāng)一個(gè)線程執(zhí)行一個(gè)任務(wù)時(shí),另外的線程可以執(zhí)行另一個(gè)完全不同的任務(wù)。和Unity的渲染過程相關(guān)的線程有三種:主線程,渲染線程和worker threads。了解哪個(gè)線程負(fù)責(zé)哪些任務(wù)的用處非常之大,一旦我們知道了在哪個(gè)線程上的任務(wù)執(zhí)行的速率最低,那么我們就應(yīng)該集中優(yōu)化在那個(gè)線程上的操作。

    以上所顯示的數(shù)據(jù)依賴于我們當(dāng)前選擇的profiler。例如,當(dāng)選中內(nèi)存時(shí),這個(gè)區(qū)域顯示例如游戲資源使用的內(nèi)存和總內(nèi)存占用等。如果選中渲染profiler,這里會(huì)顯示被渲染的對(duì)象數(shù)量或者渲染操作執(zhí)行次數(shù)等數(shù)據(jù)。

    這些profiler會(huì)提供很多詳細(xì)信息,但是我們并不總需要使用所有的profiler。實(shí)際上,我們?cè)诜治鲇螒蛐阅軙r(shí)通常只是觀察一個(gè)或者兩個(gè)profiler,而不需要觀察的我們可以通過右上角的”X”關(guān)閉,如果需要在添加回來,可以通過左上角Add Profiler。
    例如,當(dāng)我們的游戲運(yùn)行的比較慢時(shí),我們可能一開始先查看CPU usage profiler,CPU usage profiler也是在我們進(jìn)行優(yōu)化分析時(shí)最常用的Profiler。

    當(dāng)然,除了CPU usage profiler,Unity Profiler中其他的Profiler在一些場(chǎng)合也非常的有用,比如GPU、內(nèi)存、渲染等,其使用方法和CPU usage profiler也是大同小異,可以按照以上的步驟來查看并學(xué)習(xí)。

    我們?cè)谟^察數(shù)據(jù)時(shí),需要觀察的目標(biāo)有如下幾點(diǎn):

    CPU:

    • GC Allow: 任何一次性內(nèi)存分配大于2KB的選項(xiàng)。
      每幀都具有20B以上內(nèi)存分配的選項(xiàng) 。

    GC相關(guān)的問題和優(yōu)化,在之后我們會(huì)詳細(xì)的介紹。

    • Time ms:

      注意占用5ms以上的選項(xiàng)

    內(nèi)存 :

    • Texture: 檢查是否有重復(fù)資源和超大內(nèi)存是否需要壓縮等.
    • AnimationClip: 重點(diǎn)檢查是否有重復(fù)資源.。
    • Mesh: 重點(diǎn)檢查是否有重復(fù)資源。

    實(shí)際項(xiàng)目中的優(yōu)化建議

    在了解了Unity Profiler后,現(xiàn)在我們?cè)谝粋€(gè)實(shí)際項(xiàng)目中來進(jìn)行一次性能分析。同時(shí)來了解一般在實(shí)際項(xiàng)目中,主要會(huì)引起也是我們主要去觀察的性能問題出現(xiàn)在什么地方。

    以下是我做的一個(gè)簡(jiǎn)單的游戲項(xiàng)目,并未做任何性能優(yōu)化并且有大量引起性能問題的代碼,可以更方便大家觀察其性能問題。

    我們來看一下在CPU usage profiler面板中的可觀察項(xiàng),在項(xiàng)目中我們可以先關(guān)閉VSync垂直同步來提高幀率。

    下圖中我關(guān)閉了除VSync之外的顯示,可以看到VSync的消耗

    具體步驟是edit->project settings->Quality,在Inspector面板中,V Sync count選擇don’t Sync.

    我們來簡(jiǎn)單的介紹一下什么是垂直同步,以及關(guān)閉它之后會(huì)發(fā)生什么。

    要理解垂直同步,首先明白顯示器的工作原理。

    顯示器上的所有圖像都是單個(gè)像素組成了水平掃描線,水平掃描線在垂直方向的堆積形成了完整的畫面,無論是隔行掃描還是逐行掃描,顯示器都有兩種同步參數(shù)——水平同步和垂直同步。
    垂直和水平是CRT顯示器中兩個(gè)基本的同步信號(hào),水平同步信號(hào)決定了CRT畫出一條橫越屏幕線的時(shí)間,垂直同步信號(hào)決定了CRT從屏幕頂部畫到底部,再返回原始位置的時(shí)間,而垂直同步代表著CRT顯示器的刷新率水準(zhǔn)。
    在游戲項(xiàng)目中,如果我們選擇等待垂直同步信號(hào)也就是打開垂直同步,在游戲中或許性能較強(qiáng)的顯卡會(huì)迅速的繪制完一屏的圖像,但是沒有垂直同步信號(hào)的到達(dá),顯卡無法繪制下一屏,只有等85單位的信號(hào)到達(dá),才可以繪制。這樣FPS自然要受到刷新率運(yùn)行值的制約。
    而如果我們選擇不等待垂直同步信號(hào),那么游戲中繪制完一屏畫面,顯卡和顯示器無需等待垂直同步信號(hào)就可以開始下一屏圖像的繪制,自然可以完全發(fā)揮顯卡的實(shí)力。
    但是,正是因?yàn)榇怪蓖降拇嬖?#xff0c;才能使得游戲進(jìn)程和顯示器刷新率同步,使得畫面更加平滑和穩(wěn)定。取消了垂直同步信號(hào),固然可以換來更快的速度,但是在圖像的連續(xù)性上勢(shì)必會(huì)打折扣。

    需要注意,LCD顯示器其實(shí)也是存在刷新率的,但其機(jī)制與CRT不同,這里不做過多贅述,但是垂直同步和水平同步對(duì)于LCD顯示器來說,一樣是有必要的。

    在關(guān)閉垂直同步后,我們繼續(xù)看我們的項(xiàng)目

    可以看到,我們以Total和Time ms排序,在圖中拉黑的項(xiàng)(Camera Render)始終排在最前面。
    Camera Render是相機(jī)渲染工作的CPU占用量,在實(shí)際項(xiàng)目中,渲染是最常見的引起性能問題的原因。 而因?yàn)殇秩径鸬男阅軉栴}的優(yōu)化是一個(gè)非常大的工程,這方面的優(yōu)化方法在我們后續(xù)的文章中會(huì)有詳細(xì)的教程去學(xué)習(xí)和分析。在這里,我們只需要先了解。
    我們這個(gè)項(xiàng)目的優(yōu)化中,無疑,渲染造成的性能損耗是一個(gè)大頭。

    如果說,在我們性能分析中,渲染已經(jīng)沒有什么問題,那么我們接下來要重點(diǎn)觀察的就是GC,也就是垃圾回收性能分析。
    我們按照GC Alloc的順序來顯示,可以看到下圖。

    在之前我們提到過,GC Alloc中,任何一次性內(nèi)存分配大于2KB的選項(xiàng),每幀都具有20B以上內(nèi)存分配的選項(xiàng) ,是需要我們重點(diǎn)關(guān)注的,顯而易見,我們的項(xiàng)目中,對(duì)于GC的優(yōu)化,也有很大的問題。

    這里我們大致介紹一下GC的機(jī)制,要想了解垃圾回收如何工作以及何時(shí)被觸發(fā),我們首先需要了解unity的內(nèi)存管理機(jī)制。Unity主要采用自動(dòng)內(nèi)存管理的機(jī)制,開發(fā)時(shí)在代碼中不需要詳細(xì)地告訴unity如何進(jìn)行內(nèi)存管理,unity內(nèi)部自身會(huì)進(jìn)行內(nèi)存管理。
    Unity內(nèi)部有兩個(gè)內(nèi)存管理池,堆內(nèi)存和棧內(nèi)存,垃圾回收主要是指堆上的內(nèi)存分配和回收,unity中會(huì)定時(shí)對(duì)堆內(nèi)存進(jìn)行GC操作。
    當(dāng)堆內(nèi)存上一個(gè)變量不再處于激活狀態(tài)的時(shí)候,其所占用的內(nèi)存并不會(huì)立刻被回收,不再使用的內(nèi)存只會(huì)在GC的時(shí)候才會(huì)被回收。
    每次運(yùn)行GC的時(shí)候,GC會(huì)檢查堆內(nèi)存上的每個(gè)存儲(chǔ)變量,對(duì)每個(gè)變量會(huì)檢測(cè)其引用是否處于激活狀態(tài),如果變量的引用不再處于激活狀態(tài),則會(huì)被標(biāo)記為可回收,被標(biāo)記的變量會(huì)被移除,其所占有的內(nèi)存會(huì)被回收到堆內(nèi)存上。

    GC操作是一個(gè)極其耗費(fèi)的操作,堆內(nèi)存上的變量或者引用越多則其運(yùn)行的操作會(huì)更多,耗費(fèi)的時(shí)間越長(zhǎng)。

    如果我們也排除了GC的問題, 那么再接下來,我們就要考慮到是否是腳本的一些問題造成性能損耗。

    這里的腳本,可能是我們自己寫的代碼,也有可能是我們使用的一些插件的代碼。在CPU usage profiler面板中,我們可以關(guān)注Script這一項(xiàng)。

    如果在一個(gè)很慢的幀中,一大部分時(shí)間被腳本運(yùn)行所消耗,這意味著這些慢的腳本可能就是引起性能問題的主因。我們可以更加深入的分析數(shù)據(jù)來確認(rèn)。

    首先我們按照Time ms來排序,然后選擇信息列表中的項(xiàng)目,如果是用戶腳本的函數(shù),那么在Profiler上方會(huì)有高亮腳本的部分。這種情況,說明游戲的性能問題是和用戶腳本相關(guān)的,如下圖中的顯示,這部分腳本性能問題一定是與我們FixedUpdate有關(guān)。

    同時(shí),我們還可以再關(guān)注一些物理、ui方面的性能問題。

    在上面我們討論的,是幾種最常見的性能問題,在實(shí)際項(xiàng)目?jī)?yōu)化中,如果有性能問題也逃不開這些,如果在這些方向都已經(jīng)達(dá)到了我們的要求,但我們的游戲仍然有性能問題,我們應(yīng)該遵循上面的方法解決問題:收集數(shù)據(jù)——>使用CPU usage profiler查看信息——>找到引起問題的函數(shù)。一旦我們知道了引起問題函數(shù)的名字,我們便可以針對(duì)性的,對(duì)其進(jìn)行優(yōu)化處理。

    6.2.2-其他性能分析工具

    在開頭我們說過,在我們進(jìn)行Unity性能優(yōu)化的過程中,最主要用的到性能分析工具包括,Unity自帶的Unity Profile,IOS端XCode Capture GPU frame以及一些第三方插件,如騰訊推出的UPA性能分析工具。

    這里我們簡(jiǎn)單的介紹一下XCode和UPA.

    Xcode是 Mac OS X上的集成開發(fā)工具。在我們打包Unity IOS的項(xiàng)目時(shí),必須使用到Xcode來幫助我們打包及發(fā)布。

    Xcode的功能也十分的強(qiáng)大,在我們開發(fā)IOS端時(shí),可以使用其GPU frame Capture 功能為我們的項(xiàng)目進(jìn)行性能優(yōu)化分析。

    在unity中,我們打包時(shí)在Run In Xcode as 選擇debug模式,并且勾選Development Build

    打包完成后,使用Xcode打開文件,在Xcode中選擇Product ——> Scheme——> Manage Schemes

    然后會(huì)出現(xiàn)如下界面

    我們雙擊這個(gè)項(xiàng)目會(huì)出現(xiàn)如下界面

    然后我們?cè)谧髠?cè)選中Run,然后在右側(cè)面板選擇Options

    在GPU frame Capture中選擇OpenGL ES或者M(jìn)etal。

    在Debug模式下運(yùn)行項(xiàng)目,當(dāng)項(xiàng)目在真機(jī)上完全加載后,就可以進(jìn)入Debug Navigator(View ——> Navigators ——> Show Debug Navigator)

    以下是GPU frame Capture具體功能的界面,在圖形化界面中,可以在游戲運(yùn)行時(shí)清晰的了解到CPU、GPU、內(nèi)存的使用情況。


    XCode的Capture GPU frame功能能高效且定量地定位到GPU中shader的消耗。

    UPA是騰訊和Unity聯(lián)合打造的一款性能分析工具,據(jù)說王者榮耀的性能優(yōu)化分析就有使用到UPA,具體的使用方法可以通過客戶端性能測(cè)試【騰訊WeTest】去了解

    總結(jié)

    以上是生活随笔為你收集整理的浅谈Unity中的优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    国产成人精品一区二区在线小狼 | 日本精品少妇一区二区三区 | 性生交片免费无码看人 | 亚拍精品一区二区三区探花 | 东京热一精品无码av | 国产亚洲视频中文字幕97精品 | 5858s亚洲色大成网站www | 少妇邻居内射在线 | 丰满少妇弄高潮了www | 久久无码专区国产精品s | 亚洲精品一区二区三区婷婷月 | 一二三四社区在线中文视频 | www成人国产高清内射 | 在教室伦流澡到高潮hnp视频 | 亚洲综合另类小说色区 | 鲁一鲁av2019在线 | v一区无码内射国产 | 色婷婷欧美在线播放内射 | 18精品久久久无码午夜福利 | 久久久成人毛片无码 | 亚洲精品午夜无码电影网 | 国产亚洲精品久久久久久大师 | 亚洲欧美中文字幕5发布 | 国产香蕉97碰碰久久人人 | 久久99精品久久久久婷婷 | 久久99久久99精品中文字幕 | 天堂а√在线中文在线 | 亚洲国产精品一区二区美利坚 | 精品厕所偷拍各类美女tp嘘嘘 | 精品人人妻人人澡人人爽人人 | 成人亚洲精品久久久久 | 国产免费无码一区二区视频 | 99精品久久毛片a片 | 少妇厨房愉情理9仑片视频 | 久久精品国产大片免费观看 | 成人亚洲精品久久久久软件 | 精品久久久久久人妻无码中文字幕 | 精品国产一区av天美传媒 | 国产内射老熟女aaaa | 少妇人妻偷人精品无码视频 | 2020久久香蕉国产线看观看 | 中文字幕无码免费久久99 | 日日干夜夜干 | 国产在线aaa片一区二区99 | 欧美日韩视频无码一区二区三 | 久久国产精品_国产精品 | 丰满妇女强制高潮18xxxx | 精品熟女少妇av免费观看 | 国产亚洲精品久久久久久久久动漫 | 麻豆国产人妻欲求不满谁演的 | 亚洲成熟女人毛毛耸耸多 | 亚洲国产欧美国产综合一区 | 午夜无码人妻av大片色欲 | 久久人人爽人人人人片 | 亚洲一区二区三区国产精华液 | 色综合久久网 | 欧洲精品码一区二区三区免费看 | 亚洲 日韩 欧美 成人 在线观看 | 在线欧美精品一区二区三区 | 国产精品久久久久9999小说 | 青青久在线视频免费观看 | 在线天堂新版最新版在线8 | 无码人妻丰满熟妇区五十路百度 | 国产在线精品一区二区高清不卡 | 东京一本一道一二三区 | 无码吃奶揉捏奶头高潮视频 | 国色天香社区在线视频 | 亚洲理论电影在线观看 | 国产精品免费大片 | 色综合久久88色综合天天 | 国产尤物精品视频 | 亚洲va欧美va天堂v国产综合 | 高潮喷水的毛片 | 亚洲熟熟妇xxxx | 人人爽人人澡人人高潮 | 国产办公室秘书无码精品99 | 亚洲第一无码av无码专区 | 欧美老妇交乱视频在线观看 | 国产香蕉尹人综合在线观看 | 国产乱人伦偷精品视频 | 成人无码视频免费播放 | 日韩精品久久久肉伦网站 | 天天做天天爱天天爽综合网 | 国产精品美女久久久 | 免费人成在线观看网站 | 蜜桃视频韩日免费播放 | 色婷婷综合中文久久一本 | 秋霞成人午夜鲁丝一区二区三区 | 激情人妻另类人妻伦 | 天天做天天爱天天爽综合网 | 久久99精品国产麻豆 | 最新版天堂资源中文官网 | 少妇被粗大的猛进出69影院 | 国产精品亚洲综合色区韩国 | 扒开双腿疯狂进出爽爽爽视频 | 久久亚洲精品成人无码 | 国产内射爽爽大片视频社区在线 | 少妇性l交大片欧洲热妇乱xxx | 男人和女人高潮免费网站 | 亚洲精品一区二区三区四区五区 | 精品久久久久久亚洲精品 | 狠狠色噜噜狠狠狠7777奇米 | 四虎影视成人永久免费观看视频 | 日本一卡2卡3卡四卡精品网站 | 日本www一道久久久免费榴莲 | 大屁股大乳丰满人妻 | 欧美精品无码一区二区三区 | 中文字幕无码av波多野吉衣 | 亚洲人成网站色7799 | 久久综合给久久狠狠97色 | 亚洲熟妇色xxxxx亚洲 | 久久精品成人欧美大片 | 漂亮人妻洗澡被公强 日日躁 | 久久精品丝袜高跟鞋 | 久久久精品人妻久久影视 | av在线亚洲欧洲日产一区二区 | 亚洲精品一区二区三区四区五区 | 人妻少妇精品无码专区动漫 | 亚洲精品久久久久久久久久久 | 亚洲中文字幕久久无码 | 久久综合给合久久狠狠狠97色 | 人妻少妇精品视频专区 | 宝宝好涨水快流出来免费视频 | 国产在线一区二区三区四区五区 | 亚洲精品综合一区二区三区在线 | 天天综合网天天综合色 | 黑人巨大精品欧美黑寡妇 | 扒开双腿吃奶呻吟做受视频 | 亚洲色欲色欲天天天www | 久久久www成人免费毛片 | 无码成人精品区在线观看 | 88国产精品欧美一区二区三区 | 永久黄网站色视频免费直播 | 色 综合 欧美 亚洲 国产 | 疯狂三人交性欧美 | 国产精品无码永久免费888 | 久久国内精品自在自线 | 国产精品理论片在线观看 | 亚洲爆乳大丰满无码专区 | 在线观看欧美一区二区三区 | 55夜色66夜色国产精品视频 | 精品欧美一区二区三区久久久 | 少妇一晚三次一区二区三区 | 性做久久久久久久免费看 | 又湿又紧又大又爽a视频国产 | 精品一区二区三区无码免费视频 | 人妻有码中文字幕在线 | 亚洲国产高清在线观看视频 | 伊人久久大香线焦av综合影院 | 亚洲小说春色综合另类 | 精品一区二区不卡无码av | 久久精品国产日本波多野结衣 | 日本va欧美va欧美va精品 | 亚洲国产精品久久久久久 | 国产特级毛片aaaaaaa高清 | 久久人人97超碰a片精品 | 日韩欧美成人免费观看 | 大乳丰满人妻中文字幕日本 | 国产精品多人p群无码 | 国产日产欧产精品精品app | 丰腴饱满的极品熟妇 | 国产av一区二区三区最新精品 | 国产黑色丝袜在线播放 | 亚洲小说春色综合另类 | 亚洲熟妇色xxxxx欧美老妇y | 成人无码影片精品久久久 | 1000部夫妻午夜免费 | 亚洲中文字幕va福利 | 国产成人精品久久亚洲高清不卡 | 亚洲自偷自偷在线制服 | 日本一区二区三区免费高清 | 在线播放免费人成毛片乱码 | 欧美精品在线观看 | 丁香花在线影院观看在线播放 | 国产特级毛片aaaaaa高潮流水 | 少妇被粗大的猛进出69影院 | 久久国产劲爆∧v内射 | 大肉大捧一进一出视频出来呀 | 日本一卡二卡不卡视频查询 | 人妻体内射精一区二区三四 | 色噜噜亚洲男人的天堂 | 中文字幕人妻无码一区二区三区 | 国产精品人人爽人人做我的可爱 | 麻豆国产丝袜白领秘书在线观看 | 久久熟妇人妻午夜寂寞影院 | 亚洲色欲久久久综合网东京热 | 国产一区二区不卡老阿姨 | 亚洲精品久久久久久久久久久 | 亚洲毛片av日韩av无码 | 97夜夜澡人人双人人人喊 | 国产日产欧产精品精品app | 久久久精品成人免费观看 | 99久久久无码国产精品免费 | 成人精品一区二区三区中文字幕 | 人人妻人人澡人人爽精品欧美 | 国产亚洲欧美在线专区 | 在线亚洲高清揄拍自拍一品区 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 亚洲成a人片在线观看日本 | 国产99久久精品一区二区 | √天堂资源地址中文在线 | 亚洲日韩乱码中文无码蜜桃臀网站 | 亚洲欧美精品aaaaaa片 | 精品国产av色一区二区深夜久久 | 东京一本一道一二三区 | 中文字幕av日韩精品一区二区 | 女人被男人躁得好爽免费视频 | 亚洲一区二区三区四区 | 亚洲日本一区二区三区在线 | 久久久精品成人免费观看 | 亚洲精品午夜国产va久久成人 | 国产在线一区二区三区四区五区 | 人人超人人超碰超国产 | 国产高清av在线播放 | 久久久久久亚洲精品a片成人 | 色欲av亚洲一区无码少妇 | 成人女人看片免费视频放人 | 中文久久乱码一区二区 | 亚洲色无码一区二区三区 | 娇妻被黑人粗大高潮白浆 | 少妇无码av无码专区在线观看 | 欧美丰满熟妇xxxx | 日韩欧美成人免费观看 | 久久精品99久久香蕉国产色戒 | 波多野42部无码喷潮在线 | 亚洲欧美色中文字幕在线 | 少妇人妻偷人精品无码视频 | 国产人妻大战黑人第1集 | 欧美 丝袜 自拍 制服 另类 | 熟妇女人妻丰满少妇中文字幕 | 午夜福利不卡在线视频 | 成人精品天堂一区二区三区 | 亚洲午夜福利在线观看 | 人妻少妇精品视频专区 | www一区二区www免费 | 亚洲精品一区二区三区在线观看 | 大肉大捧一进一出好爽视频 | 中文字幕无线码免费人妻 | 日日碰狠狠躁久久躁蜜桃 | 日韩成人一区二区三区在线观看 | 国产精品无码mv在线观看 | 久久久久久久久888 | 欧美猛少妇色xxxxx | 日本高清一区免费中文视频 | 成人精品视频一区二区三区尤物 | 国产一区二区三区四区五区加勒比 | 人人妻在人人 | 在线看片无码永久免费视频 | 国产成人无码av一区二区 | 亚洲国产欧美日韩精品一区二区三区 | 国产一区二区三区四区五区加勒比 | 黑人大群体交免费视频 | 人妻插b视频一区二区三区 | 日韩av无码一区二区三区 | 一本久道高清无码视频 | 国产成人精品必看 | 精品欧美一区二区三区久久久 | 精品国产一区二区三区四区在线看 | 亚洲精品综合一区二区三区在线 | 亚洲精品一区二区三区在线观看 | 人人妻人人澡人人爽欧美一区 | 在线精品国产一区二区三区 | 欧美精品无码一区二区三区 | 在线亚洲高清揄拍自拍一品区 | 在线 国产 欧美 亚洲 天堂 | 亚洲a无码综合a国产av中文 | 色一情一乱一伦一区二区三欧美 | 麻豆成人精品国产免费 | 色爱情人网站 | 精品乱码久久久久久久 | 久久无码专区国产精品s | 国产色xx群视频射精 | 色综合天天综合狠狠爱 | 国产免费观看黄av片 | 中文字幕久久久久人妻 | 久久综合九色综合欧美狠狠 | 欧美一区二区三区视频在线观看 | 大乳丰满人妻中文字幕日本 | 狠狠cao日日穞夜夜穞av | 国模大胆一区二区三区 | 国产精品嫩草久久久久 | 又紧又大又爽精品一区二区 | 久久午夜夜伦鲁鲁片无码免费 | 特级做a爰片毛片免费69 | 小泽玛莉亚一区二区视频在线 | 成人试看120秒体验区 | 午夜精品一区二区三区在线观看 | 亚洲七七久久桃花影院 | 国色天香社区在线视频 | 又大又紧又粉嫩18p少妇 | 中文亚洲成a人片在线观看 | 狠狠色噜噜狠狠狠狠7777米奇 | 性欧美videos高清精品 | 爆乳一区二区三区无码 | 蜜桃视频插满18在线观看 | 久久无码人妻影院 | 久久www免费人成人片 | 97夜夜澡人人双人人人喊 | 亚洲精品成人福利网站 | 国精产品一品二品国精品69xx | 国产高清av在线播放 | 国产三级久久久精品麻豆三级 | 国产热a欧美热a在线视频 | 欧美日韩久久久精品a片 | 中文字幕无线码 | 中文字幕精品av一区二区五区 | 激情国产av做激情国产爱 | 欧美熟妇另类久久久久久多毛 | 免费网站看v片在线18禁无码 | 欧美国产亚洲日韩在线二区 | 国产成人综合美国十次 | 亚洲中文字幕va福利 | 国产黑色丝袜在线播放 | 久在线观看福利视频 | 亚洲精品一区国产 | 成人精品视频一区二区三区尤物 | 一区二区三区高清视频一 | 大地资源中文第3页 | √天堂资源地址中文在线 | 男女爱爱好爽视频免费看 | 久久天天躁夜夜躁狠狠 | 国产农村妇女高潮大叫 | 亚洲成色www久久网站 | 精品日本一区二区三区在线观看 | 亚洲一区av无码专区在线观看 | 精品人妻人人做人人爽夜夜爽 | 日韩av激情在线观看 | 极品尤物被啪到呻吟喷水 | 99久久人妻精品免费一区 | 久久精品无码一区二区三区 | 大地资源网第二页免费观看 | 少妇无码av无码专区在线观看 | 欧美zoozzooz性欧美 | 无码精品人妻一区二区三区av | 亚洲精品成人av在线 | 国产色xx群视频射精 | 天堂亚洲免费视频 | 国产午夜福利100集发布 | 欧美自拍另类欧美综合图片区 | 国产乡下妇女做爰 | 国产艳妇av在线观看果冻传媒 | 久久久久成人片免费观看蜜芽 | 99久久精品国产一区二区蜜芽 | 无码国内精品人妻少妇 | 狠狠色丁香久久婷婷综合五月 | 国产精品国产自线拍免费软件 | www一区二区www免费 | 大色综合色综合网站 | 国产精品久久久久久久影院 | 夜夜夜高潮夜夜爽夜夜爰爰 | 久久亚洲精品成人无码 | 国产成人综合在线女婷五月99播放 | 人妻无码久久精品人妻 | 青草视频在线播放 | 亚洲欧美日韩国产精品一区二区 | 亚洲第一无码av无码专区 | 亚洲人成无码网www | 中文亚洲成a人片在线观看 | 秋霞成人午夜鲁丝一区二区三区 | а√天堂www在线天堂小说 | 久久久婷婷五月亚洲97号色 | 欧美三级a做爰在线观看 | 5858s亚洲色大成网站www | 欧美人与物videos另类 | 日本又色又爽又黄的a片18禁 | 欧美成人免费全部网站 | 国产极品美女高潮无套在线观看 | 国产精品对白交换视频 | 免费视频欧美无人区码 | 久久精品国产日本波多野结衣 | 亚洲精品国偷拍自产在线麻豆 | 亚洲国产精品久久久久久 | 精品一区二区三区无码免费视频 | 老子影院午夜伦不卡 | 亚洲伊人久久精品影院 | 精品成在人线av无码免费看 | 亚洲精品一区二区三区四区五区 | 亚洲中文字幕无码中字 | 亚洲精品国产精品乱码不卡 | 色综合视频一区二区三区 | 动漫av网站免费观看 | 中文字幕中文有码在线 | 最近中文2019字幕第二页 | 久久久久国色av免费观看性色 | 国产精品亚洲а∨无码播放麻豆 | 日本精品人妻无码免费大全 | 中文字幕中文有码在线 | 国产精品久久久久久久影院 | 国产午夜亚洲精品不卡下载 | 久久精品人人做人人综合试看 | 大肉大捧一进一出视频出来呀 | 国产农村妇女高潮大叫 | 精品久久久久香蕉网 | 欧美日韩一区二区三区自拍 | 欧美国产日韩亚洲中文 | 国产xxx69麻豆国语对白 | 亚洲中文字幕无码一久久区 | 欧美国产日韩亚洲中文 | 久久国产劲爆∧v内射 | 精品久久久久久人妻无码中文字幕 | 欧美一区二区三区视频在线观看 | 亚洲国产午夜精品理论片 | 无码人妻丰满熟妇区五十路百度 | 欧美熟妇另类久久久久久多毛 | 2019nv天堂香蕉在线观看 | 久久久国产精品无码免费专区 | 久久精品国产99久久6动漫 | 久久无码人妻影院 | 无码av最新清无码专区吞精 | 国产成人一区二区三区在线观看 | 久久国产精品_国产精品 | 无码乱肉视频免费大全合集 | 亚洲综合在线一区二区三区 | 国产亚洲视频中文字幕97精品 | 老熟妇乱子伦牲交视频 | 精品国产一区二区三区av 性色 | 亚洲综合精品香蕉久久网 | 久久亚洲精品中文字幕无男同 | 亚洲天堂2017无码中文 | 日韩av无码一区二区三区不卡 | 无码精品国产va在线观看dvd | 国内老熟妇对白xxxxhd | 中文字幕无码免费久久9一区9 | 国产内射爽爽大片视频社区在线 | 亚洲码国产精品高潮在线 | 精品无码国产自产拍在线观看蜜 | 欧美精品无码一区二区三区 | 免费人成网站视频在线观看 | 玩弄中年熟妇正在播放 | 老太婆性杂交欧美肥老太 | 久久久久成人片免费观看蜜芽 | 欧美激情综合亚洲一二区 | 纯爱无遮挡h肉动漫在线播放 | 野狼第一精品社区 | 国内精品久久毛片一区二区 | 亚洲成熟女人毛毛耸耸多 | 久在线观看福利视频 | 婷婷五月综合激情中文字幕 | 成人无码影片精品久久久 | 中文字幕无码日韩欧毛 | 最新国产麻豆aⅴ精品无码 | 日韩在线不卡免费视频一区 | 婷婷色婷婷开心五月四房播播 | 一本加勒比波多野结衣 | 亚洲国产午夜精品理论片 | 日本精品少妇一区二区三区 | 国模大胆一区二区三区 | 天天av天天av天天透 | 天下第一社区视频www日本 | 波多野结衣乳巨码无在线观看 | 少女韩国电视剧在线观看完整 | 97夜夜澡人人双人人人喊 | 欧美熟妇另类久久久久久多毛 | 国产亚洲欧美日韩亚洲中文色 | 亚洲日韩一区二区三区 | 亚洲欧洲中文日韩av乱码 | 久久午夜无码鲁丝片秋霞 | 大地资源网第二页免费观看 | 国产精品鲁鲁鲁 | 宝宝好涨水快流出来免费视频 | 亚洲天堂2017无码 | 亚洲 日韩 欧美 成人 在线观看 | 欧洲美熟女乱又伦 | 久久久成人毛片无码 | 亚洲人成网站色7799 | 久久精品成人欧美大片 | 亚洲熟妇色xxxxx欧美老妇 | 无套内谢老熟女 | 久久精品99久久香蕉国产色戒 | 奇米影视7777久久精品人人爽 | 性欧美大战久久久久久久 | 亚洲一区二区三区香蕉 | 亚洲成色在线综合网站 | 婷婷综合久久中文字幕蜜桃三电影 | 亚洲人成影院在线无码按摩店 | 曰韩无码二三区中文字幕 | 国产极品美女高潮无套在线观看 | 狠狠色丁香久久婷婷综合五月 | 亚洲精品美女久久久久久久 | 日本一区二区三区免费播放 | 大肉大捧一进一出视频出来呀 | 亚洲另类伦春色综合小说 | 精品国产aⅴ无码一区二区 | 无码人妻久久一区二区三区不卡 | 国产明星裸体无码xxxx视频 | 性欧美疯狂xxxxbbbb | 国产xxx69麻豆国语对白 | 国产乡下妇女做爰 | 在线播放亚洲第一字幕 | 中文字幕 人妻熟女 | 国产午夜手机精彩视频 | av小次郎收藏 | 大地资源网第二页免费观看 | 中文字幕精品av一区二区五区 | 久久无码专区国产精品s | 高清不卡一区二区三区 | 国产xxx69麻豆国语对白 | 一本加勒比波多野结衣 | 国产精品国产自线拍免费软件 | 欧美日韩一区二区三区自拍 | 高潮毛片无遮挡高清免费 | 国产97在线 | 亚洲 | 学生妹亚洲一区二区 | 亚洲熟妇色xxxxx亚洲 | 欧美日韩亚洲国产精品 | 岛国片人妻三上悠亚 | 亚洲精品欧美二区三区中文字幕 | 夜精品a片一区二区三区无码白浆 | 天天躁夜夜躁狠狠是什么心态 | 国产精品久久久久久久9999 | 性史性农村dvd毛片 | 色婷婷综合激情综在线播放 | 国产精品国产三级国产专播 | 亚洲日本va中文字幕 | 亚洲色欲色欲天天天www | 色婷婷av一区二区三区之红樱桃 | 国产无av码在线观看 | 日韩精品无码一本二本三本色 | 日韩亚洲欧美中文高清在线 | 欧美丰满老熟妇xxxxx性 | 国产三级精品三级男人的天堂 | 国产亚洲视频中文字幕97精品 | 久久午夜夜伦鲁鲁片无码免费 | 正在播放老肥熟妇露脸 | 国产情侣作爱视频免费观看 | 亚洲成av人在线观看网址 | 日本丰满熟妇videos | 色五月五月丁香亚洲综合网 | 色情久久久av熟女人妻网站 | 欧美成人免费全部网站 | 亚洲人交乣女bbw | √8天堂资源地址中文在线 | 亚洲另类伦春色综合小说 | 国产精品人人爽人人做我的可爱 | 天堂亚洲免费视频 | 亚洲精品一区二区三区在线观看 | 免费人成在线视频无码 | 帮老师解开蕾丝奶罩吸乳网站 | 美女扒开屁股让男人桶 | 午夜无码人妻av大片色欲 | 国内综合精品午夜久久资源 | 樱花草在线播放免费中文 | 丰满少妇高潮惨叫视频 | 中文字幕av日韩精品一区二区 | 亚洲欧洲日本无在线码 | 西西人体www44rt大胆高清 | 日日干夜夜干 | 免费无码一区二区三区蜜桃大 | 伊人久久婷婷五月综合97色 | 久久久精品人妻久久影视 | 国产福利视频一区二区 | 最新国产麻豆aⅴ精品无码 | 在线亚洲高清揄拍自拍一品区 | 又大又紧又粉嫩18p少妇 | 国产熟妇高潮叫床视频播放 | 精品国产一区二区三区四区在线看 | 亚洲一区二区三区无码久久 | 一个人免费观看的www视频 | 日日碰狠狠躁久久躁蜜桃 | 日韩亚洲欧美中文高清在线 | 无码人妻精品一区二区三区不卡 | 欧美性生交活xxxxxdddd | 天下第一社区视频www日本 | 久久午夜夜伦鲁鲁片无码免费 | 秋霞特色aa大片 | 欧美日韩在线亚洲综合国产人 | 久久精品无码一区二区三区 | 7777奇米四色成人眼影 | 真人与拘做受免费视频一 | 中文字幕av日韩精品一区二区 | 亚洲熟悉妇女xxx妇女av | 中文字幕无码热在线视频 | 在线a亚洲视频播放在线观看 | 国产成人无码专区 | 99久久婷婷国产综合精品青草免费 | 黑人巨大精品欧美一区二区 | 亚洲一区二区三区在线观看网站 | 四虎影视成人永久免费观看视频 | 性色av无码免费一区二区三区 | 性开放的女人aaa片 | 色欲av亚洲一区无码少妇 | 国产精品久久久久7777 | 欧美老熟妇乱xxxxx | 久久久久免费看成人影片 | 久久精品丝袜高跟鞋 | 亚洲欧美国产精品专区久久 | 国产香蕉尹人视频在线 | 99久久精品无码一区二区毛片 | 熟女少妇在线视频播放 | 小泽玛莉亚一区二区视频在线 | 夜夜夜高潮夜夜爽夜夜爰爰 | 99久久精品国产一区二区蜜芽 | 波多野42部无码喷潮在线 | 色综合久久久无码中文字幕 | 亚洲日本一区二区三区在线 | 色综合久久久久综合一本到桃花网 | 婷婷丁香五月天综合东京热 | 成人亚洲精品久久久久软件 | 亚洲一区二区三区偷拍女厕 | 啦啦啦www在线观看免费视频 | 国产97人人超碰caoprom | 午夜性刺激在线视频免费 | 欧美日韩一区二区综合 | 欧美熟妇另类久久久久久多毛 | 熟女俱乐部五十路六十路av | 在线精品国产一区二区三区 | 一二三四在线观看免费视频 | 亚洲国产成人a精品不卡在线 | 131美女爱做视频 | 亚洲色偷偷男人的天堂 | 中国女人内谢69xxxxxa片 | 精品夜夜澡人妻无码av蜜桃 | 在线a亚洲视频播放在线观看 | 日韩av无码一区二区三区 | 捆绑白丝粉色jk震动捧喷白浆 | 亚洲爆乳精品无码一区二区三区 | 亚洲欧美中文字幕5发布 | 亚洲欧洲日本综合aⅴ在线 | 日韩精品一区二区av在线 | 国产精品高潮呻吟av久久4虎 | 精品国产国产综合精品 | 无码一区二区三区在线观看 | 97久久国产亚洲精品超碰热 | 日韩精品一区二区av在线 | 人妻天天爽夜夜爽一区二区 | 国产肉丝袜在线观看 | 四虎国产精品一区二区 | 欧美日韩久久久精品a片 | 内射白嫩少妇超碰 | 无码人妻出轨黑人中文字幕 | 亚洲乱码中文字幕在线 | 999久久久国产精品消防器材 | 日日麻批免费40分钟无码 | 国产午夜无码视频在线观看 | 日本在线高清不卡免费播放 | 网友自拍区视频精品 | 麻豆精品国产精华精华液好用吗 | 激情人妻另类人妻伦 | 日日摸日日碰夜夜爽av | 日韩精品久久久肉伦网站 | 亚洲aⅴ无码成人网站国产app | 天堂亚洲免费视频 | 日日天日日夜日日摸 | 在线天堂新版最新版在线8 | 成人女人看片免费视频放人 | 无码av中文字幕免费放 | 久久成人a毛片免费观看网站 | 国产精品18久久久久久麻辣 | 日日摸夜夜摸狠狠摸婷婷 | 国产成人综合美国十次 | 天天爽夜夜爽夜夜爽 | 免费网站看v片在线18禁无码 | 樱花草在线社区www | 内射巨臀欧美在线视频 | 日本又色又爽又黄的a片18禁 | 国产福利视频一区二区 | 日本欧美一区二区三区乱码 | 小泽玛莉亚一区二区视频在线 | 亚洲成色在线综合网站 | 精品无码成人片一区二区98 | 国产 精品 自在自线 | 中文字幕无码av波多野吉衣 | 成人无码视频在线观看网站 | 国内精品人妻无码久久久影院 | 亚洲爆乳无码专区 | 国产一区二区三区日韩精品 | 久久 国产 尿 小便 嘘嘘 | 兔费看少妇性l交大片免费 | 97色伦图片97综合影院 | 国语精品一区二区三区 | 少妇人妻偷人精品无码视频 | 国产香蕉97碰碰久久人人 | 少女韩国电视剧在线观看完整 | 激情爆乳一区二区三区 | 国精品人妻无码一区二区三区蜜柚 | 东京热男人av天堂 | 国产手机在线αⅴ片无码观看 | 激情内射亚州一区二区三区爱妻 | 无人区乱码一区二区三区 | 少妇无码av无码专区在线观看 | 国产精品无套呻吟在线 | 性欧美大战久久久久久久 | 欧美日韩久久久精品a片 | 欧美色就是色 | 成人免费视频一区二区 | 天堂亚洲免费视频 | 亚洲熟妇色xxxxx欧美老妇y | 丰满人妻翻云覆雨呻吟视频 | 久久99精品国产.久久久久 | 国产97人人超碰caoprom | 国产亚av手机在线观看 | 最新版天堂资源中文官网 | 亚洲中文字幕av在天堂 | 亚洲小说春色综合另类 | 亚洲熟悉妇女xxx妇女av | 午夜不卡av免费 一本久久a久久精品vr综合 | 久久精品人人做人人综合试看 | 日韩人妻无码中文字幕视频 | 国产三级久久久精品麻豆三级 | 我要看www免费看插插视频 | 亚洲中文字幕无码中字 | 女人被男人爽到呻吟的视频 | 波多野结衣高清一区二区三区 | 人妻与老人中文字幕 | 98国产精品综合一区二区三区 | 精品国偷自产在线 | 在线播放无码字幕亚洲 | 精品国产乱码久久久久乱码 | 亚洲狠狠色丁香婷婷综合 | 色婷婷欧美在线播放内射 | 熟女俱乐部五十路六十路av | 精品久久久久香蕉网 | 小sao货水好多真紧h无码视频 | 国产成人精品一区二区在线小狼 | 少妇被粗大的猛进出69影院 | av人摸人人人澡人人超碰下载 | 狠狠色丁香久久婷婷综合五月 | 精品久久久久香蕉网 | 日韩欧美成人免费观看 | 国产精品a成v人在线播放 | 国产精品无码久久av | 精品乱码久久久久久久 | 久久99精品国产麻豆蜜芽 | 国产熟女一区二区三区四区五区 | а天堂中文在线官网 | 久久精品人妻少妇一区二区三区 | 2019午夜福利不卡片在线 | 东北女人啪啪对白 | 国产精品视频免费播放 | 日产精品99久久久久久 | 日韩少妇白浆无码系列 | 精品无码国产自产拍在线观看蜜 | 精品国产精品久久一区免费式 | 亚洲国精产品一二二线 | 欧美亚洲国产一区二区三区 | 野狼第一精品社区 | 国产两女互慰高潮视频在线观看 | 沈阳熟女露脸对白视频 | 中文字幕 人妻熟女 | 国产区女主播在线观看 | 黑人巨大精品欧美黑寡妇 | 麻豆成人精品国产免费 | 欧美日韩精品 | 国产黄在线观看免费观看不卡 | 国产午夜无码精品免费看 | 日本爽爽爽爽爽爽在线观看免 | 欧美丰满少妇xxxx性 | 亚洲午夜久久久影院 | 久久亚洲中文字幕精品一区 | 少妇厨房愉情理9仑片视频 | 中文字幕无线码免费人妻 | 男人和女人高潮免费网站 | 久久久久免费看成人影片 | 日韩欧美成人免费观看 | 国产午夜视频在线观看 | 97久久精品无码一区二区 | 欧美怡红院免费全部视频 | 国产亚洲美女精品久久久2020 | 午夜福利试看120秒体验区 | 国产在线aaa片一区二区99 | 日韩av无码一区二区三区不卡 | 欧美性生交活xxxxxdddd | 久久久久久久女国产乱让韩 | 亚洲国产精品久久久久久 | 水蜜桃亚洲一二三四在线 | 狠狠色噜噜狠狠狠7777奇米 | 久久亚洲日韩精品一区二区三区 | 丰满少妇弄高潮了www | 久久久久久久女国产乱让韩 | 国产深夜福利视频在线 | 亚洲无人区一区二区三区 | 蜜桃av抽搐高潮一区二区 | 久久人人爽人人人人片 | 精品成在人线av无码免费看 | 2020久久香蕉国产线看观看 | 婷婷丁香六月激情综合啪 | 欧美日韩人成综合在线播放 | 麻豆人妻少妇精品无码专区 | 国产精品久久久 | 久久99精品国产.久久久久 | 日韩精品无码免费一区二区三区 | 亚洲日韩精品欧美一区二区 | 亚洲成熟女人毛毛耸耸多 | 国产精品对白交换视频 | 狂野欧美激情性xxxx | 久久久国产一区二区三区 | 天海翼激烈高潮到腰振不止 | 野外少妇愉情中文字幕 | 自拍偷自拍亚洲精品被多人伦好爽 | 久久精品国产日本波多野结衣 | 亚洲一区二区三区偷拍女厕 | 中文精品无码中文字幕无码专区 | 国产在线一区二区三区四区五区 | 天天躁日日躁狠狠躁免费麻豆 | 丰满少妇人妻久久久久久 | 亚洲狠狠色丁香婷婷综合 | 无人区乱码一区二区三区 | 日韩欧美中文字幕在线三区 | 成人av无码一区二区三区 | 日日橹狠狠爱欧美视频 | 乱码午夜-极国产极内射 | 少妇厨房愉情理9仑片视频 | 国产熟妇高潮叫床视频播放 | 亚洲欧美中文字幕5发布 | 亚洲熟妇色xxxxx欧美老妇y | 国内精品久久久久久中文字幕 | 特级做a爰片毛片免费69 | 国产激情精品一区二区三区 | 久久久久久a亚洲欧洲av冫 | 国产av久久久久精东av | 东北女人啪啪对白 | 欧美放荡的少妇 | 久久久国产精品无码免费专区 | 在线成人www免费观看视频 | 成人综合网亚洲伊人 | 久久久久成人精品免费播放动漫 | 色欲综合久久中文字幕网 | 亚洲第一无码av无码专区 | 久久 国产 尿 小便 嘘嘘 | 精品一区二区三区波多野结衣 | 水蜜桃色314在线观看 | 真人与拘做受免费视频 | 18禁黄网站男男禁片免费观看 | 免费无码午夜福利片69 | 免费无码午夜福利片69 | 色窝窝无码一区二区三区色欲 | 欧美激情综合亚洲一二区 | 国产在线无码精品电影网 | 美女毛片一区二区三区四区 | 免费观看黄网站 | 55夜色66夜色国产精品视频 | 十八禁真人啪啪免费网站 | 国产无av码在线观看 | 毛片内射-百度 | 色欲av亚洲一区无码少妇 | 国语自产偷拍精品视频偷 | 久久天天躁夜夜躁狠狠 | 成熟女人特级毛片www免费 | 无码av最新清无码专区吞精 | 人妻aⅴ无码一区二区三区 | 久久精品国产日本波多野结衣 | 自拍偷自拍亚洲精品被多人伦好爽 | 国产在线精品一区二区三区直播 | 亚洲精品一区二区三区四区五区 | 野狼第一精品社区 | 最近免费中文字幕中文高清百度 | 国产人妻大战黑人第1集 | 日日碰狠狠躁久久躁蜜桃 | 乱码av麻豆丝袜熟女系列 | 久久亚洲a片com人成 | √天堂中文官网8在线 | 亚洲色欲色欲天天天www | 欧美日韩视频无码一区二区三 | 最新国产乱人伦偷精品免费网站 | 久青草影院在线观看国产 | 中文字幕人妻无码一区二区三区 | 国产av剧情md精品麻豆 | 亚洲国产精华液网站w | 又色又爽又黄的美女裸体网站 | a在线观看免费网站大全 | 欧美人与牲动交xxxx | 又大又黄又粗又爽的免费视频 | 亚洲精品一区三区三区在线观看 | 中文字幕人妻无码一区二区三区 | 亚洲欧美综合区丁香五月小说 | 无遮挡国产高潮视频免费观看 | 无码午夜成人1000部免费视频 | 久久久久久久人妻无码中文字幕爆 | 色老头在线一区二区三区 | 漂亮人妻洗澡被公强 日日躁 | 久久无码专区国产精品s | 99久久人妻精品免费一区 | 疯狂三人交性欧美 | 久久 国产 尿 小便 嘘嘘 | 性做久久久久久久久 | 亚洲成av人在线观看网址 | 免费国产黄网站在线观看 | 学生妹亚洲一区二区 | 99久久99久久免费精品蜜桃 | 精品夜夜澡人妻无码av蜜桃 | 中国女人内谢69xxxx | 中文字幕精品av一区二区五区 | 亚洲综合伊人久久大杳蕉 | 黑人粗大猛烈进出高潮视频 | 中文字幕无码免费久久99 | 国产精品毛片一区二区 | 亚洲国产精品成人久久蜜臀 | 亚洲s码欧洲m码国产av | 日本精品人妻无码77777 天堂一区人妻无码 | 亚洲中文字幕av在天堂 | av人摸人人人澡人人超碰下载 | 亚洲国产精品成人久久蜜臀 | 中文字幕人妻丝袜二区 | 亚洲精品一区二区三区婷婷月 | 无码人妻丰满熟妇区五十路百度 | 久久亚洲a片com人成 | 午夜福利一区二区三区在线观看 | 国产精品久久国产三级国 | 欧洲vodafone精品性 | 又粗又大又硬毛片免费看 | 小鲜肉自慰网站xnxx | 日本高清一区免费中文视频 | 欧洲极品少妇 | 国内精品一区二区三区不卡 | aⅴ在线视频男人的天堂 | 国产麻豆精品一区二区三区v视界 | 精品厕所偷拍各类美女tp嘘嘘 | 男女下面进入的视频免费午夜 | 久久亚洲中文字幕无码 | 国产卡一卡二卡三 | 国产 浪潮av性色四虎 | 久久精品人妻少妇一区二区三区 | 精品熟女少妇av免费观看 | 中文字幕乱码人妻二区三区 | 狠狠色噜噜狠狠狠7777奇米 | 国产精品久久国产精品99 | 全黄性性激高免费视频 | 乱人伦人妻中文字幕无码久久网 | 国产欧美精品一区二区三区 | 天天做天天爱天天爽综合网 | 午夜免费福利小电影 | 国产乱人伦av在线无码 | 最新国产麻豆aⅴ精品无码 | 国产又爽又猛又粗的视频a片 | 97精品人妻一区二区三区香蕉 | 国产性生交xxxxx无码 | 免费网站看v片在线18禁无码 | 国产又爽又黄又刺激的视频 | 亚洲国产精品毛片av不卡在线 | 精品国产一区二区三区四区在线看 | 无码乱肉视频免费大全合集 | 亚洲欧美国产精品专区久久 | 丁香啪啪综合成人亚洲 | 亚洲精品国偷拍自产在线观看蜜桃 | 日本va欧美va欧美va精品 | 夜精品a片一区二区三区无码白浆 | 色综合久久久久综合一本到桃花网 | 无遮挡国产高潮视频免费观看 | 亚洲色欲色欲欲www在线 | 精品人妻人人做人人爽夜夜爽 | 亚洲高清偷拍一区二区三区 | 在线观看国产一区二区三区 | 粗大的内捧猛烈进出视频 | 亚洲人亚洲人成电影网站色 | 亚洲午夜无码久久 | 国产亚洲精品精品国产亚洲综合 | 欧美激情内射喷水高潮 | 国产精华av午夜在线观看 | 日韩av无码中文无码电影 | 在线播放免费人成毛片乱码 | 蜜桃无码一区二区三区 | 久久午夜无码鲁丝片秋霞 | 欧美精品一区二区精品久久 | 狠狠色欧美亚洲狠狠色www | 色综合久久久无码网中文 | 中文字幕无码人妻少妇免费 | 人妻体内射精一区二区三四 | 精品久久久无码人妻字幂 | 一本色道久久综合亚洲精品不卡 | 欧美激情一区二区三区成人 | 欧美午夜特黄aaaaaa片 | 日韩av激情在线观看 | 亚洲日韩av片在线观看 | 亚洲精品一区二区三区婷婷月 | 国产乱人伦av在线无码 | 黑人巨大精品欧美一区二区 | 精品久久久久香蕉网 | 午夜精品久久久内射近拍高清 | 国产农村妇女高潮大叫 | 亚洲成av人片在线观看无码不卡 | 国产成人综合色在线观看网站 | 亚洲一区二区三区在线观看网站 | 牲欲强的熟妇农村老妇女视频 | 成 人 网 站国产免费观看 | 亚洲一区av无码专区在线观看 | 国产精品亚洲lv粉色 | 99精品视频在线观看免费 | 欧美 日韩 人妻 高清 中文 | 人人妻人人澡人人爽精品欧美 | 亚洲日韩av一区二区三区四区 | 97精品人妻一区二区三区香蕉 | 日韩精品无码免费一区二区三区 | 夫妻免费无码v看片 | 久9re热视频这里只有精品 | 欧美人与牲动交xxxx | 无码av免费一区二区三区试看 | 一本无码人妻在中文字幕免费 | 欧美 日韩 亚洲 在线 | 宝宝好涨水快流出来免费视频 | 中文字幕日韩精品一区二区三区 | 一本色道久久综合亚洲精品不卡 | 免费国产成人高清在线观看网站 | 久久亚洲a片com人成 | 久久久精品人妻久久影视 | 无码人妻av免费一区二区三区 | 全黄性性激高免费视频 | 国产亚洲日韩欧美另类第八页 | 国产午夜福利亚洲第一 | 久久久成人毛片无码 | 日韩精品无码一本二本三本色 | 无码精品国产va在线观看dvd | 国产精品a成v人在线播放 | 少妇激情av一区二区 | 国产精品-区区久久久狼 | a在线观看免费网站大全 | 免费无码一区二区三区蜜桃大 | 蜜桃视频插满18在线观看 | 激情内射亚州一区二区三区爱妻 | 国产av一区二区三区最新精品 | 大肉大捧一进一出视频出来呀 | 无遮挡国产高潮视频免费观看 | 人妻无码久久精品人妻 | 熟女少妇在线视频播放 | 国产 浪潮av性色四虎 | 全黄性性激高免费视频 | 免费观看又污又黄的网站 | 国产真实伦对白全集 | 鲁鲁鲁爽爽爽在线视频观看 | 日韩视频 中文字幕 视频一区 | 国产激情综合五月久久 | 老熟妇仑乱视频一区二区 | а√天堂www在线天堂小说 | 俺去俺来也在线www色官网 | 日韩精品成人一区二区三区 | 丰腴饱满的极品熟妇 | 国产精品久久国产精品99 | 全黄性性激高免费视频 | 欧美一区二区三区视频在线观看 | 午夜嘿嘿嘿影院 | 久久精品国产亚洲精品 | 人人澡人摸人人添 | 欧美怡红院免费全部视频 | 性色av无码免费一区二区三区 | 亚洲人交乣女bbw | 国产精品久久久午夜夜伦鲁鲁 | 美女黄网站人色视频免费国产 | 久久国产精品二国产精品 | 中文字幕无码热在线视频 | 精品无码一区二区三区的天堂 | 日本一区二区三区免费高清 | 丰满少妇女裸体bbw | 国产亚洲日韩欧美另类第八页 | 性开放的女人aaa片 | 国产亚洲精品久久久久久久 | 亚洲精品一区二区三区在线 | 亚洲一区二区三区国产精华液 | 狠狠色噜噜狠狠狠7777奇米 | 毛片内射-百度 | 日韩 欧美 动漫 国产 制服 | 国产乱人无码伦av在线a | 99久久婷婷国产综合精品青草免费 | 人人爽人人澡人人人妻 | 狂野欧美激情性xxxx | 日日麻批免费40分钟无码 | 精品无人国产偷自产在线 | 亚洲综合伊人久久大杳蕉 | 无码成人精品区在线观看 | 欧美高清在线精品一区 | 国产亚洲日韩欧美另类第八页 | 国产激情艳情在线看视频 | 亚洲毛片av日韩av无码 | 日本高清一区免费中文视频 | 久久久久久九九精品久 | 精品国产福利一区二区 | 极品尤物被啪到呻吟喷水 | 亚洲国产精品成人久久蜜臀 | 欧洲欧美人成视频在线 | 美女扒开屁股让男人桶 | 国产三级精品三级男人的天堂 | 高清无码午夜福利视频 | 中文字幕日产无线码一区 | 亚洲国产精品毛片av不卡在线 | 午夜精品久久久内射近拍高清 | 性生交大片免费看女人按摩摩 | 99久久婷婷国产综合精品青草免费 | 国产精品无码一区二区三区不卡 | 99国产精品白浆在线观看免费 | 国产av一区二区精品久久凹凸 | 亚洲一区二区观看播放 | 亚洲日本一区二区三区在线 | 天堂а√在线中文在线 | 亚洲日本va午夜在线电影 | 波多野结衣aⅴ在线 | 对白脏话肉麻粗话av | 成人无码视频在线观看网站 | 日韩欧美成人免费观看 | 俺去俺来也在线www色官网 | 亚洲另类伦春色综合小说 | 18黄暴禁片在线观看 | 国产精品亚洲一区二区三区喷水 | 免费观看的无遮挡av | 久久久久久a亚洲欧洲av冫 | 日本在线高清不卡免费播放 | 色噜噜亚洲男人的天堂 | 亚洲成a人一区二区三区 | 免费观看的无遮挡av | 国产在线精品一区二区高清不卡 | 未满成年国产在线观看 | 领导边摸边吃奶边做爽在线观看 | 男人扒开女人内裤强吻桶进去 | 欧美性猛交xxxx富婆 | 国产精品va在线观看无码 | 强开小婷嫩苞又嫩又紧视频 | 初尝人妻少妇中文字幕 | 精品一二三区久久aaa片 | 久久亚洲中文字幕无码 | 国产午夜福利100集发布 | 日本成熟视频免费视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 欧美zoozzooz性欧美 | 久久综合九色综合欧美狠狠 | 亚洲欧美中文字幕5发布 | 99久久久无码国产aaa精品 | a在线观看免费网站大全 | 亚洲精品一区二区三区婷婷月 | 亚洲国产精品久久久久久 | 男女超爽视频免费播放 | 亚洲男人av天堂午夜在 | 久久午夜无码鲁丝片 | 成人一区二区免费视频 | 丰满少妇高潮惨叫视频 | 麻豆av传媒蜜桃天美传媒 | 久久亚洲日韩精品一区二区三区 | 国产成人精品一区二区在线小狼 | 久久久久99精品成人片 | 国产97色在线 | 免 | 国产人成高清在线视频99最全资源 | 精品午夜福利在线观看 | 精品欧洲av无码一区二区三区 | 国产精品久久久一区二区三区 | 日韩成人一区二区三区在线观看 | 麻花豆传媒剧国产免费mv在线 | 性色欲网站人妻丰满中文久久不卡 | 色婷婷久久一区二区三区麻豆 | 成人影院yy111111在线观看 | 日本精品高清一区二区 | 国产精品毛片一区二区 | 国产莉萝无码av在线播放 | 精品人妻中文字幕有码在线 | 日韩视频 中文字幕 视频一区 | 欧美怡红院免费全部视频 | 沈阳熟女露脸对白视频 | 亚洲娇小与黑人巨大交 | 日日夜夜撸啊撸 | 亚洲色偷偷男人的天堂 | 国产97人人超碰caoprom | 水蜜桃色314在线观看 | 国产美女极度色诱视频www | 亚洲国产精品无码久久久久高潮 | 在线播放免费人成毛片乱码 | 真人与拘做受免费视频 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 丝袜足控一区二区三区 | 久久午夜无码鲁丝片午夜精品 | 好屌草这里只有精品 | 久精品国产欧美亚洲色aⅴ大片 | 亚洲人交乣女bbw | 久久午夜无码鲁丝片午夜精品 | 日韩av激情在线观看 | 欧美日韩精品 | 中文字幕无码免费久久99 | 亚洲熟妇色xxxxx欧美老妇y | 久久五月精品中文字幕 | 日韩精品无码免费一区二区三区 | 久久午夜无码鲁丝片 | 美女极度色诱视频国产 | 亚洲精品综合五月久久小说 | 亚洲爆乳精品无码一区二区三区 | 日本欧美一区二区三区乱码 | 国产精品igao视频网 | 日本高清一区免费中文视频 | 三上悠亚人妻中文字幕在线 | 小泽玛莉亚一区二区视频在线 | 一本加勒比波多野结衣 | 女人被爽到呻吟gif动态图视看 | 国产亚洲精品久久久久久大师 | 成人试看120秒体验区 | 亚洲一区av无码专区在线观看 | 精品无码国产一区二区三区av | 少妇人妻偷人精品无码视频 | 人人妻人人澡人人爽欧美一区 | 女人和拘做爰正片视频 | 色欲综合久久中文字幕网 | 国产无遮挡吃胸膜奶免费看 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 伊人久久大香线焦av综合影院 | 巨爆乳无码视频在线观看 | 久久人人爽人人爽人人片ⅴ | av在线亚洲欧洲日产一区二区 | 牛和人交xxxx欧美 | 午夜无码人妻av大片色欲 | 久久精品国产大片免费观看 | 精品国产一区二区三区四区在线看 | 一本久道久久综合婷婷五月 | 亚洲精品美女久久久久久久 | 日本丰满熟妇videos | 人妻无码αv中文字幕久久琪琪布 | 色综合久久久久综合一本到桃花网 | 好爽又高潮了毛片免费下载 | 欧美黑人性暴力猛交喷水 | 成人影院yy111111在线观看 | 亚洲熟妇自偷自拍另类 | 亚洲中文字幕在线无码一区二区 | 久久熟妇人妻午夜寂寞影院 | 精品成在人线av无码免费看 | 国产精品久久久一区二区三区 | 美女扒开屁股让男人桶 | 日韩欧美中文字幕在线三区 | 久久久精品国产sm最大网站 | 久久亚洲精品成人无码 | 亚洲成熟女人毛毛耸耸多 | 中文字幕人妻无码一夲道 | 色五月丁香五月综合五月 | 亚洲va中文字幕无码久久不卡 | 东京热男人av天堂 | 日本爽爽爽爽爽爽在线观看免 | 日韩精品a片一区二区三区妖精 | 精品无码成人片一区二区98 | 午夜嘿嘿嘿影院 | 精品国偷自产在线视频 | 国产激情艳情在线看视频 | 中文字幕亚洲情99在线 | 激情内射日本一区二区三区 | 亚洲 激情 小说 另类 欧美 | 成人片黄网站色大片免费观看 | 97精品人妻一区二区三区香蕉 | 亚洲gv猛男gv无码男同 | 少妇的肉体aa片免费 | 小泽玛莉亚一区二区视频在线 | 一本色道久久综合狠狠躁 | 在线看片无码永久免费视频 | 亚洲国产av精品一区二区蜜芽 | 亚洲综合在线一区二区三区 | 日本www一道久久久免费榴莲 | 欧美大屁股xxxxhd黑色 | 欧美精品一区二区精品久久 | 少妇厨房愉情理9仑片视频 | 亚洲无人区一区二区三区 | 国产偷国产偷精品高清尤物 | 国产三级精品三级男人的天堂 | 久久久久久a亚洲欧洲av冫 | 特级做a爰片毛片免费69 | 国产亚洲精品久久久久久国模美 | 内射欧美老妇wbb | 牲欲强的熟妇农村老妇女视频 | 5858s亚洲色大成网站www | 岛国片人妻三上悠亚 | av无码不卡在线观看免费 | www国产精品内射老师 | 黑人巨大精品欧美一区二区 | 久久99国产综合精品 | 免费看少妇作爱视频 | аⅴ资源天堂资源库在线 | 久久久久久久女国产乱让韩 | 国产成人无码午夜视频在线观看 | 亚洲国产成人av在线观看 | 大肉大捧一进一出好爽视频 | a在线亚洲男人的天堂 | 欧美国产日韩亚洲中文 | 欧美第一黄网免费网站 | 内射欧美老妇wbb | 久久99精品国产.久久久久 | 国产艳妇av在线观看果冻传媒 | 精品国产一区二区三区四区在线看 | 色五月五月丁香亚洲综合网 | 国产一精品一av一免费 | 人人澡人摸人人添 | 精品夜夜澡人妻无码av蜜桃 | 国产综合色产在线精品 | 亚洲日韩中文字幕在线播放 | 超碰97人人做人人爱少妇 | 福利一区二区三区视频在线观看 | 少妇性l交大片 | 俄罗斯老熟妇色xxxx | 无码人妻黑人中文字幕 | 在线播放无码字幕亚洲 | 久久精品女人天堂av免费观看 | 55夜色66夜色国产精品视频 | 色欲久久久天天天综合网精品 | 美女极度色诱视频国产 | 久久99久久99精品中文字幕 | 久激情内射婷内射蜜桃人妖 | 亚拍精品一区二区三区探花 | 清纯唯美经典一区二区 | 亚洲 a v无 码免 费 成 人 a v | 国产xxx69麻豆国语对白 | 麻豆精产国品 | 免费人成在线观看网站 | 国产精品美女久久久久av爽李琼 | 自拍偷自拍亚洲精品被多人伦好爽 | 国内综合精品午夜久久资源 | 欧美亚洲国产一区二区三区 | 自拍偷自拍亚洲精品被多人伦好爽 | 国产又爽又猛又粗的视频a片 | 亚洲国产欧美国产综合一区 | 国产精品亚洲а∨无码播放麻豆 | av在线亚洲欧洲日产一区二区 | 亚洲第一网站男人都懂 | 成年女人永久免费看片 | 国内丰满熟女出轨videos | 女人被男人躁得好爽免费视频 | 性欧美熟妇videofreesex | 精品国产一区二区三区av 性色 | 国产亚洲欧美日韩亚洲中文色 | 午夜嘿嘿嘿影院 | 国产精品无码永久免费888 | 国产va免费精品观看 | 成人免费视频视频在线观看 免费 | 伊人久久婷婷五月综合97色 | 在线a亚洲视频播放在线观看 | 嫩b人妻精品一区二区三区 | 乱中年女人伦av三区 | 大肉大捧一进一出好爽视频 | 久久国产精品二国产精品 | 熟女俱乐部五十路六十路av | 无码人妻久久一区二区三区不卡 | 中文字幕日韩精品一区二区三区 | 亚洲成av人综合在线观看 | 一个人免费观看的www视频 | 天堂无码人妻精品一区二区三区 | 精品一区二区三区波多野结衣 | 国产精品免费大片 | 国产两女互慰高潮视频在线观看 | 国产成人无码午夜视频在线观看 | а√资源新版在线天堂 | 蜜臀aⅴ国产精品久久久国产老师 | 红桃av一区二区三区在线无码av | 国产乱码精品一品二品 | 欧美性猛交xxxx富婆 | 亚洲经典千人经典日产 | 丁香啪啪综合成人亚洲 | 性色欲情网站iwww九文堂 | 99精品无人区乱码1区2区3区 | 国产在线精品一区二区高清不卡 | 99久久亚洲精品无码毛片 | 麻豆精品国产精华精华液好用吗 | 人妻人人添人妻人人爱 | 性开放的女人aaa片 | 色 综合 欧美 亚洲 国产 | 中文字幕无码免费久久9一区9 | 久久久久se色偷偷亚洲精品av | 亚洲娇小与黑人巨大交 | 免费网站看v片在线18禁无码 | 国产av久久久久精东av | 成人综合网亚洲伊人 | 3d动漫精品啪啪一区二区中 | 成人亚洲精品久久久久软件 | 国产无遮挡又黄又爽又色 | 中文字幕 亚洲精品 第1页 | 国产片av国语在线观看 | 欧美丰满熟妇xxxx | a国产一区二区免费入口 | 黑人粗大猛烈进出高潮视频 | 丰满少妇熟乱xxxxx视频 | 131美女爱做视频 | 永久免费观看美女裸体的网站 | 99久久精品无码一区二区毛片 | 蜜桃无码一区二区三区 | 婷婷丁香五月天综合东京热 | 成人影院yy111111在线观看 | 欧洲美熟女乱又伦 | 人人澡人人妻人人爽人人蜜桃 | 精品国产成人一区二区三区 | 老熟妇仑乱视频一区二区 | 又粗又大又硬又长又爽 | 精品无码一区二区三区的天堂 | 国精产品一品二品国精品69xx | 在线天堂新版最新版在线8 | 久久久久99精品国产片 | 成人欧美一区二区三区 | 99久久久无码国产精品免费 | 一本色道久久综合亚洲精品不卡 | 亚洲欧美中文字幕5发布 | 精品成在人线av无码免费看 | 精品aⅴ一区二区三区 | 日本一区二区更新不卡 | 男女猛烈xx00免费视频试看 | 久久精品99久久香蕉国产色戒 | 国产av一区二区精品久久凹凸 | 强奷人妻日本中文字幕 | 国产精品久久久久久无码 | 亚拍精品一区二区三区探花 | 国产精品亚洲а∨无码播放麻豆 | 亚洲综合另类小说色区 | 免费观看又污又黄的网站 | 久久久久亚洲精品中文字幕 | 又大又紧又粉嫩18p少妇 | 真人与拘做受免费视频一 | 人人妻人人澡人人爽人人精品浪潮 | 熟妇女人妻丰满少妇中文字幕 | 又紧又大又爽精品一区二区 | 免费中文字幕日韩欧美 | 久久亚洲国产成人精品性色 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 无码帝国www无码专区色综合 | 夜精品a片一区二区三区无码白浆 | 国产两女互慰高潮视频在线观看 | 中文字幕中文有码在线 | 日韩人妻无码一区二区三区久久99 | 欧美第一黄网免费网站 | 中文字幕人妻无码一区二区三区 | 丰满少妇人妻久久久久久 | 欧美国产日韩亚洲中文 | 性做久久久久久久久 | 野狼第一精品社区 | 一本久久伊人热热精品中文字幕 | 九九热爱视频精品 | 377p欧洲日本亚洲大胆 | 国产亚洲精品精品国产亚洲综合 | 国内精品人妻无码久久久影院蜜桃 | 色综合视频一区二区三区 | 久9re热视频这里只有精品 | 99riav国产精品视频 | 国产日产欧产精品精品app | 欧美自拍另类欧美综合图片区 | 国产亲子乱弄免费视频 | 欧美兽交xxxx×视频 | 欧洲极品少妇 | 亚洲自偷自拍另类第1页 | 国内揄拍国内精品少妇国语 | 亚洲精品中文字幕久久久久 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 野外少妇愉情中文字幕 | 亚洲日韩中文字幕在线播放 | 天天爽夜夜爽夜夜爽 | 狂野欧美性猛xxxx乱大交 | 国产卡一卡二卡三 | 女人被爽到呻吟gif动态图视看 | 亚洲日韩av片在线观看 | 亚洲天堂2017无码 | 熟妇人妻激情偷爽文 | 少妇性俱乐部纵欲狂欢电影 | 丰满肥臀大屁股熟妇激情视频 | 人妻少妇精品无码专区二区 | 亚洲精品国产精品乱码不卡 | 久久综合香蕉国产蜜臀av | 国产三级久久久精品麻豆三级 | 日日鲁鲁鲁夜夜爽爽狠狠 | 久久久久se色偷偷亚洲精品av | 日本成熟视频免费视频 | 高潮毛片无遮挡高清免费视频 | 亚洲色欲久久久综合网东京热 | 无人区乱码一区二区三区 | 久久aⅴ免费观看 | 午夜熟女插插xx免费视频 | 免费国产黄网站在线观看 | 日韩人妻无码中文字幕视频 | 国产手机在线αⅴ片无码观看 | 少妇高潮喷潮久久久影院 | 日日天干夜夜狠狠爱 | 爆乳一区二区三区无码 | 国产三级久久久精品麻豆三级 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 中文无码伦av中文字幕 | 亚洲国产精品无码久久久久高潮 | 18精品久久久无码午夜福利 | 精品人人妻人人澡人人爽人人 | 一本精品99久久精品77 | 国产一区二区三区精品视频 | 精品国产精品久久一区免费式 | 久久午夜夜伦鲁鲁片无码免费 | 久久久久成人精品免费播放动漫 | 亚洲成av人片天堂网无码】 | 久久国产精品精品国产色婷婷 | 中文精品久久久久人妻不卡 | 装睡被陌生人摸出水好爽 | 99久久无码一区人妻 | 精品无码国产一区二区三区av | 国产午夜福利100集发布 | 亚洲精品国偷拍自产在线麻豆 | 亚洲精品久久久久中文第一幕 | 日日摸天天摸爽爽狠狠97 | 亚洲中文字幕成人无码 | 国产免费久久精品国产传媒 | 国产成人综合在线女婷五月99播放 | 性做久久久久久久久 | 免费观看激色视频网站 | 欧美性色19p | 国内揄拍国内精品人妻 | 久久精品人妻少妇一区二区三区 | 日本精品人妻无码免费大全 | 亚洲熟妇色xxxxx欧美老妇 | 无遮挡国产高潮视频免费观看 | 亲嘴扒胸摸屁股激烈网站 | 成 人影片 免费观看 | 老司机亚洲精品影院 | 日欧一片内射va在线影院 | 99精品视频在线观看免费 | 日日鲁鲁鲁夜夜爽爽狠狠 | 亚洲人成网站色7799 | 夜先锋av资源网站 | 美女黄网站人色视频免费国产 | 国产精品永久免费视频 | 精品无码一区二区三区爱欲 | 少妇激情av一区二区 | 秋霞成人午夜鲁丝一区二区三区 | 欧美一区二区三区视频在线观看 | 少妇厨房愉情理9仑片视频 | 好男人www社区 | 伊人久久大香线蕉av一区二区 | 男女猛烈xx00免费视频试看 | 丰满诱人的人妻3 | 激情国产av做激情国产爱 | 亚洲精品中文字幕 | 久久亚洲中文字幕精品一区 | 特黄特色大片免费播放器图片 | 国产免费无码一区二区视频 | 亚洲精品中文字幕乱码 | 欧美乱妇无乱码大黄a片 | 玩弄人妻少妇500系列视频 | 国产又粗又硬又大爽黄老大爷视 | 乱码午夜-极国产极内射 | 98国产精品综合一区二区三区 | 97色伦图片97综合影院 | 麻豆md0077饥渴少妇 | 久久无码专区国产精品s | 亚洲区小说区激情区图片区 | 扒开双腿吃奶呻吟做受视频 | 久久久久亚洲精品男人的天堂 | 亚洲色大成网站www国产 | 国产精品人人妻人人爽 | 亚洲一区二区三区四区 | 成人精品视频一区二区三区尤物 | 乱中年女人伦av三区 | 欧美日韩一区二区三区自拍 | 亚洲天堂2017无码中文 | 欧美老妇交乱视频在线观看 | 久久精品国产一区二区三区肥胖 | 蜜臀aⅴ国产精品久久久国产老师 | 又大又紧又粉嫩18p少妇 | 成人无码精品一区二区三区 | 国产精品久久久久久亚洲毛片 | 精品少妇爆乳无码av无码专区 | 日本精品久久久久中文字幕 | 国产小呦泬泬99精品 | 爱做久久久久久 | 99久久精品日本一区二区免费 | aⅴ亚洲 日韩 色 图网站 播放 | 精品少妇爆乳无码av无码专区 | 国产乡下妇女做爰 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 亚洲一区二区观看播放 | 亚洲第一网站男人都懂 | 国产亚洲美女精品久久久2020 | 荫蒂添的好舒服视频囗交 | 久久精品国产日本波多野结衣 | 国产内射爽爽大片视频社区在线 | 免费国产成人高清在线观看网站 | 国产成人精品一区二区在线小狼 | 亚洲欧美色中文字幕在线 | 西西人体www44rt大胆高清 | 东京一本一道一二三区 | 女人被男人躁得好爽免费视频 | 国产特级毛片aaaaaaa高清 | aⅴ亚洲 日韩 色 图网站 播放 | 亚洲va中文字幕无码久久不卡 | 任你躁在线精品免费 | 欧美亚洲国产一区二区三区 | 青草视频在线播放 | 骚片av蜜桃精品一区 | 无码午夜成人1000部免费视频 | 午夜无码人妻av大片色欲 | 国产卡一卡二卡三 | 啦啦啦www在线观看免费视频 | 国产乡下妇女做爰 | 国产一区二区三区精品视频 | 99久久久无码国产精品免费 | 亚洲精品久久久久中文第一幕 | 老司机亚洲精品影院 | 国产香蕉尹人视频在线 | 天堂久久天堂av色综合 | 中文字幕无码热在线视频 | 老熟妇仑乱视频一区二区 | 少女韩国电视剧在线观看完整 | 亚洲区小说区激情区图片区 | 日韩精品无码免费一区二区三区 | 俺去俺来也www色官网 | 性欧美大战久久久久久久 | 人人妻人人澡人人爽人人精品 | 老头边吃奶边弄进去呻吟 | 国产成人无码av在线影院 | 麻豆成人精品国产免费 | www国产精品内射老师 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 少妇邻居内射在线 | 18禁黄网站男男禁片免费观看 | 国产又爽又黄又刺激的视频 | 国产黄在线观看免费观看不卡 | 亚洲娇小与黑人巨大交 | 给我免费的视频在线观看 | 久久人妻内射无码一区三区 | 成人亚洲精品久久久久软件 | 一区二区三区乱码在线 | 欧洲 | 300部国产真实乱 | 国产午夜福利100集发布 | 精品成人av一区二区三区 | 精品国产乱码久久久久乱码 | 国产精品美女久久久网av | 日本免费一区二区三区最新 | 精品日本一区二区三区在线观看 | 蜜臀aⅴ国产精品久久久国产老师 | 久久精品国产大片免费观看 | 少妇被黑人到高潮喷出白浆 | 中文字幕人妻无码一区二区三区 | 亚洲国产午夜精品理论片 | 久久五月精品中文字幕 | 老熟女重囗味hdxx69 | 日韩人妻系列无码专区 | 激情内射亚州一区二区三区爱妻 | 欧美老妇交乱视频在线观看 | 国产农村妇女高潮大叫 | 激情人妻另类人妻伦 | 成人aaa片一区国产精品 | 免费男性肉肉影院 | 九九热爱视频精品 | 18精品久久久无码午夜福利 | 内射白嫩少妇超碰 | 国产莉萝无码av在线播放 | 日本www一道久久久免费榴莲 | 国产黑色丝袜在线播放 | 国内精品人妻无码久久久影院 | 免费视频欧美无人区码 | 日日天日日夜日日摸 | 最近免费中文字幕中文高清百度 | 国产人成高清在线视频99最全资源 | 鲁大师影院在线观看 | 国产午夜视频在线观看 | 300部国产真实乱 | 欧美人与物videos另类 | 久久精品国产日本波多野结衣 | 欧美阿v高清资源不卡在线播放 | 日韩人妻无码一区二区三区久久99 | 小鲜肉自慰网站xnxx | av香港经典三级级 在线 | 亚洲无人区午夜福利码高清完整版 | 成人无码精品一区二区三区 | 精品一区二区三区无码免费视频 | 少妇被粗大的猛进出69影院 | 日韩精品无码一本二本三本色 | 欧美日韩在线亚洲综合国产人 | 性做久久久久久久免费看 | 乱人伦人妻中文字幕无码 | 九九久久精品国产免费看小说 | 久久久久成人片免费观看蜜芽 | 午夜福利一区二区三区在线观看 | 日韩精品无码一本二本三本色 | 成人欧美一区二区三区黑人 | 扒开双腿疯狂进出爽爽爽视频 | 亚洲精品成a人在线观看 | 免费国产黄网站在线观看 | 欧美一区二区三区 | 天天拍夜夜添久久精品大 | 乱人伦人妻中文字幕无码久久网 | 岛国片人妻三上悠亚 | 亚洲日本在线电影 | 中文字幕av无码一区二区三区电影 | 欧美喷潮久久久xxxxx | 欧美亚洲国产一区二区三区 | 亚洲日韩av片在线观看 | 天堂无码人妻精品一区二区三区 | 鲁一鲁av2019在线 | 欧美真人作爱免费视频 | 国产精品美女久久久久av爽李琼 | 国产特级毛片aaaaaaa高清 | 一区二区传媒有限公司 | 国产精品久久久av久久久 | 日日碰狠狠躁久久躁蜜桃 | 九九综合va免费看 | 亚洲成色www久久网站 | 国产极品视觉盛宴 | 国产办公室秘书无码精品99 | 天天爽夜夜爽夜夜爽 | 久青草影院在线观看国产 | 无码免费一区二区三区 | 精品 日韩 国产 欧美 视频 | 婷婷丁香五月天综合东京热 |