大概作了大半年的VR開發,HTCVive上與room scale和手柄控制器、激光相關的開發作過,gearvr使用oculus sdk開發作過,使用Cardboard作普通vr app在android和ios上發佈也作過。html
vr設備呢,HTCVive和oculus搞過,gearvr和普通Cardboard類的手機vr搞過,LG的新的glass接過,露光嚴重,idealens、還有一大票的國產一體機,pico、小米,嗯作的好的目前的確仍是那幾個大廠的。java
因爲我參與的項目主要圍繞視頻播放的功能,因此大型3d場景接觸的倒很少,然而仍是有不少須要優化的點,爲何呢,由於作的視頻播放自己就須要對大於1080p的視頻作解碼、在unity中渲染,對cpu和gpu消耗都很大,擠佔了部分性能,因此對其餘邏輯和渲染部分的性能要求更高。android
VR開發中的優化主要圍繞兩部分吧,一部分是因爲VR的特殊場景,雙眼渲染,且對幀率要求高,因此對性能要求也高,還有vr場景下一些特殊要求。另外一部分是傳統unity性能優化部分,對程序和美術都有要求。unity相關的優化網上已經有不少優秀的文章了,我在這隻根據VR開發與傳統unity開發的區別,分享一些優化的建議。ios
歡迎下載咱們的appc#
由於HTCVive和gearvr作的開發比較多,先說說這兩個設備卡的表現,對於HTCVive而言,若是程序執行時卡頓好比loading或者什麼,通常會優雅的回到HTCVive的一個默認場景,對用戶還算比較友好,而對於gearvr而言,若是卡頓影響了渲染或者幀率低,那麼用戶頭轉動的時候能明顯看到周圍來不及渲染的黑的地方,若是渲染卡死的話,只剩最後一幀渲染的畫面,周圍的空間都是黑的。緩存
對於PC而言,咱們配置的顯卡至少也會是970+吧,性能都比較好,cpu、渲染、IO等性能都比較高,可是到了移動端,相應操做性能都會變差,以前對比過一些操做,好比圖片動態加載,在editor下可能只要幾毫秒最多20幾毫秒,到了移動端可能都要幾十毫秒甚至2-500毫秒的都有,那麼幀率下降的簡直不要不要的。因此對於unity而言,不光在editor下看性能指標,也要利用profiler觀察在移動設備的性能。咱們在開發過程當中和測試中都要不斷的進行性能優化。性能優化
傳統遊戲也會作不少的性能優化,可是卻能夠有不少經常使用的解決方案,例如爲了解決資源包大的問題,將資源經過異步下載並動態加載,爲了減小加載的損耗,那麼大不了加一個loading畫面,而loading時通常而言隨便卡,不太須要關注操做的阻塞延遲和幀率,由於loading時無需響應用戶操做。甚至有的遊戲按一個按鈕也會進行阻塞,大不了出個loading嘛反正用戶也會等。服務器
對於VR應用,用戶都是能夠自由操做轉頭的,一旦卡頓,影響幀率,直接會影響用戶視野轉動,影響體驗,同時下降幀率刷新後,用戶會有眩暈感,那麼就很失敗。網絡
通常何時會發生卡頓呢,對於vr程序開發而言,每每出如今場景切換時資源加載
、初始化腳本邏輯執行
,例如monobehaviour的awake和start裏包含的大量的邏輯,甚至你覺得使用了協程就沒有問題,然而協程在首次執行時第一個yield前可能也包含了大量的邏輯。還有運行時動態資源加載
以及常見的每幀處理事情過多致使降幀
。多線程
unity提供了一些性能指標查看工具,好比profiler和frame debug。
profiler能夠看cpu、render、內存等性能消耗,通常能夠看出每一幀哪些操做分別消耗了多少時間,找到瓶頸進行優化。例如我以前在pc上看性能貌似都還能夠,可是在gearvr移動端就明顯的看到像Resource.Load()
這種操做過多的佔用了時間因而優化掉。
另外注意沒必要要的log記得清理,不然在profiler裏會佔用不少時間。
profiler也能夠實時查看unity程序在android和ios上運行時的性能表現。
framedebug能夠方便的查看一幀都進行了哪些渲染,能夠用來優化drawcall,在作vr開發的時候,由於雙眼渲染,因此drawcall比普通程序也會高不少,正常表現是2倍的drawcall,具體平臺就算進行了必定的優化,看起來每每也要多50%以上的drawcall。
嗯具體優化drawcall的方式常規遊戲中也有蠻多,我只說咱們作的簡單且立竿見影的優化,由於ugui用的多,那麼用ugui的sprite pack以後drawcall能夠直接ugui中大量sprite的drawcall,再加上雙倍的渲染,drawcall的節約其實很是可觀,而不用作太多事情。
在切換場景的時候,使用異步接口進行load,仍是以前說的,同步load會致使卡頓而影響渲染。經過異步加載場景,儘可能減小阻塞的時間,由於場景加載完畢運行的時候,初始化相關例如awake和start仍是會致使必定的卡頓,這個就要經過後面的方式來解決。
例如加載一些prefab等資源,不少想load就load,或者集中在某個函數裏依次load好,可是這樣其實仍是會致使卡頓。因此能夠考慮使用協程等將資源加載分散到每一幀進行加載,這樣也能夠很快的在幾幀內加載完畢,同時幀率也幾乎不會降低。
作項目的時候,在經過profiler調查性能時,有發現某一幀幹了不少事情,致使卡頓。例如經過for循環幹什麼事情再用協程加載10張圖片,那麼這些操做雖然單獨一個操做只要2-3ms不影響幀率,可是多個累計起來可能就高達幾十ms甚至更高,就會影響幀率。
另外若是開了10個協程加載10張圖片,頗有可能在圖片下載ok以後,在同一幀以內多張圖片同時轉爲texture,這個操做很耗時,因而會累計致使卡頓,因此我也封裝了一個用來控制相似操做的協程,每一幀只會執行一次這種阻塞耗時操做。
若是實在沒辦法,那就在特殊阻塞操做以前給用戶一個預期吧,同時漸變黑屏掉,這樣全黑的狀況下,就算渲染卡頓了,用戶也看不出來。好比切換場景後開始的時候會比較卡,可能高達幾百ms甚至1秒,那麼我就給用戶預期是loading切換場景,先切到黑屏再阻塞,而後渲染ok了再恢復渲染。我看了有的app也是這樣作的。
對於vr視頻播放app而言,顯示各類網絡上的圖片是一個比較常見的事情,在vr場景下,圖片分辨率不能過低,而恰巧咱們服務器提供了一張分辨率較低的縮略圖和分辨率較高的大圖,使用小圖呢,不夠清晰,使用大圖呢,過於清晰,會形成閃的效果,同時loading大圖比較慢,不划算,因此但願獲得一個適當尺寸的圖。讓服務器去多給張合適的圖,是最快最方便的途徑,然而~好吧仍是但願在客戶端處理一下。
若是使用unity的texture相關函數,因爲unity動態生成大texture比較慢,在pc上都要幾十ms,若是到了移動端差很少要幾百ms,並且是同步阻塞操做,這個徹底不能接受。
若是使用unity多線程操做呢,然而unity多線程不能處理渲染相關的類例如texture。
或者使用基本c#實現,通常的處理方法是使用System.Drawing
,可是也不跨平臺,理論上應該有直接對圖片數據處理的辦法,可是當時也沒有那麼多精力去研究。
使用unity下載圖片並緩存到本地,寫個android的java插件,使用android多線程處理圖片,而後回調unity(此處也可封裝爲協程),這樣對unity而言就只剩下JNI的調用開銷和load適當大小圖片的開銷了。固然對於iOS平臺須要再寫一個小插件。
使用unity作vr開發,那麼優化不少也是基於傳統unity遊戲開發的優化經驗。因爲unity接觸也不夠深刻,因此基本也是參考其餘人的優化方法,逐漸去學習使用和深刻了解。
舉例參考
http://www.cnblogs.com/murong...
等等,這個unity優化相關能夠百度或者google到不少系統的文章,大同小異。優化之路漫漫。
總之傳統unity遊戲開發有不少種途徑進行優化,必要時也能夠有不少種方式避免用戶輸入和感知卡頓,能夠在某些狀況降低幀,而VR開發因爲雙眼渲染、頭部控制的存在,對性能要求更高,壓榨幀率,須要降幀的時候也須要特殊處理(例如黑屏)。
我看HTCVive上有些app在配有980的相對配置較高的機器上也很卡頓,仍是但願能夠在細節處優化,在用戶體驗上能夠流暢。
VR開發或者unity相關交流能夠郵件madcloudsong@qq .com