標籤:

【厚積薄發】大世界場景優化和載入策略

【厚積薄發】大世界場景優化和載入策略

來自專欄 UWA:簡單優化、優化簡單13 人贊了文章

這是第120篇UWA技術知識分享的推送。今天我們繼續為大家精選了若干和開發、優化相關的問題,建議閱讀時間10分鐘,認真讀完必有收穫。

UWA 問答社區:answer.uwa4d.com

UWA QQ群:465082844(僅限技術交流)

製作

Q:關於大世界 (SECTR + Terrain) 我有幾個問題:

1)市面上是否有手游(比如吃雞)使用了 SECTR 和 Terrain 來解決大世界的問題,並且實現效果還不錯的呢?另外是否有其他現成插件也適用大世界的?

2)Terrain的Draw Call有沒有什麼優化的建議?我注意到Terrain自帶的樹和草似乎都比較費。另外,水平視角的時候能看到較多場景中的內容,有什麼一般性的策略來減輕渲染負擔?

3)在SECTR的框架下,可以很容易給一個地圖分塊,但應該如何解決地表分層的問題(比如地面、建築、裝飾等)?這裡的層似乎已經不符合SECTR中Sector的概念,而是另一個維度。

4)大地圖中用何種手段解決LOD的問題比較好?SECTR提供了一個簡單的LOD方案,只是對組件(尤其是Renderer)根據其Bound來進行顯隱。SECTR是否在GC方面有坑?

5)性能上,通過AssetBundle頻繁載入和卸載子場景(這需要修改 SECTR_Chunk),如何能減少卡頓?

A1:首先需要說明,雖然我在博客里推薦過SECTR這套插件,但是我們沒有在項目中用,所以對於這套插件的了解只是在「玩過」的水平,所以下面的內容有不少是憑藉經驗的猜想,僅供題主參考。

1)目前貌似在手游上用SECTR+Terrain的項目還不多,反正我還沒了解到真正這麼在做的。其一是SECTR對於移動端可能沒有做過特定優化,大部分做無縫大世界的項目可能會參考插件自己實現一套,而非直接使用插件;其二,個人的經驗來說,Terrain在移動端上還是比較耗的,尤其是Unity這樣不方便自己改實現的商業引擎,後期優化的壓力可能會比較大,而且對於沒有源碼的小團隊來說只能調整配置...關於其他插件,我了解過的還有World Streamer,原理和SECTR略有不同,也是供參考。我的感覺是這些插件都是針對PC或者主機平台實現的,雖說在移動端上也許已經可以使用了,但是未必針對移動端做過很好的優化。

2)Terrain的使用,反正在一年多前我們項目立項的時候,在手機上使用Terrain還不是一件性能上推薦的事情,隨著吃雞的普及以及硬體性能的提升,應該有一些項目已經在大量地使用Terrain了吧,優化的Guideline就留給有經驗的這些朋友來回答吧。老的思路就是轉換成Mesh然後減面,這個是之前比較常規的手游做法。Speed Tree生成植被,這個在移動平台上就更耗了,特別是美術不節制地使用的情況下。可以考慮配合GPU Instance等技術可以優化DrawCall等,不過這塊經驗不多,就不多聊了。

水平自由視角,是一個對於程序很大的挑戰,當然美術工作量也很大,常用的方式應該大家都比較了解了:更加全面的LOD,視錐遠平面裁剪,高低配分級來保證低配效率等等。(LOD這塊就有不少取巧的策略,比如楚留香,有些情況下遠處物體LOD不僅僅是減面和消隱,有時候會做一個遠景的遮擋物,比如大樹,在遠處用來彌補遠景物體的不足,走近的時候這東西反而消失掉……)

3)多層的概念可以參考前文提到的World Streamer,它基於距離來做消隱,可以通過layer/tag來區分地表、大物體、常規物體、細節物體等等,不同物體的消隱距離不同。印象中SECTR中也有基於距離的Loader,這塊如果不滿足可能要自己改造了。

4)LOD是個很重要的技術,做得好了可以很大程度地提升運行效率(不僅僅是渲染的),做得不好,做出負優化來也是很正常的。Unity默認提供了LodGroup這樣的組件來做LOD,原理應該跟你說的SECTR的方案一樣。根據包圍盒在視野中的渲染比例來做LOD是比較科學的做法,比單純的距離要更加科學一些,只是在實際使用中,可能不如距離直觀和設置簡單。實現得好的LOD,一方面對於大世界來說如果能夠和Stream結合起來做對於內存和加卸載的消耗來說更加友好,比如可以做到遠景只會載入低LOD的模型;另外一個方面,好的LOD結果需要美術進行非常細緻的工作來調整和設置,這裡有非常大的工作量。

所以對於LOD來說,技術方面可能沒有那麼深,反而是廣度部分要做好的優化需要考慮各個方面,包括Render、Shadow、Animation、ParticleSystem、Material、PostEffect各個方面,再乘以高中低配置形成一個矩陣,針對這個矩陣進行定製和優化。這也代表了越好的LOD效果意味著越多的工作量。

5)GC方面的坑,因為沒有使用所以不清楚,還是留給真正用過的朋友來回答吧,建議題主真正使用之前做下實際的測試。不過GC這塊,能Profile出來的基本都可以自己改進優化,改進不了的也就沒有什麼好的方式,所以個人感覺不是特別的重要。(個人體驗,大部分插件在GC方面都有優化空間……尤其這種為了兼容更寬泛的需求支持的,插件層面有些優化不好做。)

6)頓卡方面,我們自己基於AssetBundle載入的主要優化手段還是做類似LRU的緩存,內存多的設備就多做一些,少的就少做一些。沒有做預載入,因為也比較難預測。這裡的權衡就是chunk切分是要比較細還是比較粗,各有利弊,需要根據項目實際情況來做取捨。

聊了很多,大都是常規做法,可能很多內容題主也都知道。整體來說,看題主對於SECTR已經有了不少的了解,結合項目的需求來進行改進和重新實現應該問題都不大。從原理上來說,大世界動態載入很簡單(基於Unity不自己做非常細緻的場景管理的情況下),但是在實際操作中會遇到很多要處理。3D自由視角的技術挑戰還是很大的,祝題主好運。

感謝賈偉昊@UWA問答社區提供了回答

UWA:就目前我們優化過的超大地形(8kx8k)的移動遊戲來看,基本上都沒有使用SECTR+Terrain這一解決方案的,而是全部轉換成Mesh來進行無縫拼接。我們沒有使用過SECTR這一插件,所以對其分拆機理和組織方式並不了解。但是對於Terrain來說,一般研發團隊更傾向於使用Mesh來進行替換。

Terrain的優勢在於編輯十分方便,通過一些插件(比如Terrain Composer)可以快速生成基礎地形等等,但是它的Draw Call並不容易控制,至少很不直觀,內存同樣較之同等複雜程度的Mesh要大,且TerrainData的載入效率也並不高。所以,對於前期通過Terrain來進行地形編輯的團隊,後續往往會將其導出成Mesh來進行動態分塊載入。這是目前我們較為推薦的方案。

對於場景的載入,只要AssetBundle中的內容不多,Size不大,現在通過LoadFromFile+LZ4的方式來進行載入已經相當快了,現在的頓卡一般不出現在AssetBundle載入上,而是出現在AB.Load和實例化上。對此,有效地辦法是通過預載入、緩存和自己製作流式載入來緩解卡頓問題。前兩者偉昊在他的回答中已經很詳細了。流式載入則是指控制每幀中載入和實例化的資源數量,這需要根據具體的內容、情況來進行具體分析了,並沒有統一的準則可遵循,唯一要做的就是多測試、多試驗。

除上述之外,還需要以下幾點了解一下(以下為偏題話):

(1)地形切得不要過於細碎,否則會加大Culling以及後續引擎場景規劃(CreateSharedRenderScene)的開銷;

(2)超大地形的遊戲(吃雞、沙盒等)中,UI模塊的開銷較之其他遊戲(MMO、ARPG、卡牌等)要明顯降低,這其實可以給其他模塊貢獻出更多的計算空間;

(3)物理模塊的耗時在大幅提升,如果在加上一些車體載具,那麼其往往會在不注意之間加入大量的物理開銷,這是研發團隊在面對大地形開發時會遇到的新話題。

該問答來自UWA問答社區,歡迎大家轉至社區進一步交流:

關於大世界 (SECTR + Terrain) 的幾個問題?

answer.uwa4d.com圖標

物理

Q:請問Physics2D.ConvertCollision2DForScript造成的GC該怎麼優化呢?

我是如下這樣設置的:

A:在回調OnCollisionEnter2D時,Profiler中會看到Physics2D.ConvertCollision2DForScript的GC,所以如果不需要回調,在腳本中去掉這個函數。如果使用OnCollisionEnter2D,那對於這個回調產生的GC,貌似無法避免,官方論壇也對此有一些討論:

Physics.Contacts GC activity?

forum.unity.com圖標

當然題主也可以寫自己的碰撞檢測模塊,可以利用Physics2D.GetContacts介面:

Physics2D.GetContacts?

docs.unity3d.com圖標

感謝Saber@UWA問答社區提供回答,歡迎大家轉至進一步交流:

請問怎麼優化關於Physics2D.ConvertCollision2DForScript造成的gc - UWA問答: 侑虎科技官方問答社區?

answer.uwa4d.com圖標

UGUI

Q:OnBecameVisible這個回調能用在UGUI上嗎?

UWA:從UGUI的渲染機制上來講,是以Canvas為單位來合併大Mesh的(不同DrawCall對應不同的Submesh),渲染時也就按Submesh來提交DrawCall。所以CanvasRender組件實際上並不代表真正的渲染單位,理論上也就不存在包圍盒的概念,OnBecameVisible應該也是不起作用的。

該回答由UWA提供。

A2:首先計算出UI控制項的四個最值點的世界坐標。然後使用下面這個方法可以判斷是否在Camera的視錐體內:

感謝凱奧斯@UWA問答社區提供了回答

該問答來自UWA問答社區,歡迎大家轉至社區進一步交流:

請問怎麼優化關於Physics2D.ConvertCollision2DForScript造成的gc - UWA問答: 侑虎科技官方問答社區?

answer.uwa4d.com圖標

Shader

Q:我的Shader製作完後,如何可以準確地測試出它的消耗呢?

A:關於Shader的消耗統計,一種是用工具來進行非常精細的消耗分析,比如給出精準的指令數對比,方便橫向對比兩個Shader的消耗。

另外一個思路是在真機上根據實際效率的影響進行測試,針對真正的應用場景進行優化效果的驗證。簡單的方法就是針對想測試的部分做LOD區分,然後配置一個Debug按鈕來做LOD的切換,直接在設備上統計幀率的變化和Camera.Render函數的消耗變化。不過真機的測試對於不是GPU Bound的情況下看不出來幀率的變化,另外一個角度來說它不是瓶頸的話,優化的優先順序就可以考慮調低一些,當然耗電等方面還是可以有提升的。

感謝賈偉昊@UWA問答社區提供了回答,歡迎大家轉至社區進行進一步交流:

請問怎麼優化關於Physics2D.ConvertCollision2DForScript造成的gc - UWA問答: 侑虎科技官方問答社區?

answer.uwa4d.com圖標

物理

Q:我的NGUI耗時特別厲害,一查才知道NGUI會默認帶個什麼碰撞檢測的,請問這個設置在哪裡呢?感謝。

A:1)UIPanel在Start方法中會根據UICamera的類型判斷是否自動添加剛體組件,可以嘗試避免自動添加。

2)在Unity菜單Edit/Project Settings/Physics中可以設置在哪些layer上進行碰撞檢測,如圖:

感謝client@UWA問答社區提供了回答,歡迎大家轉至社區進一步交流:

NGUI怎麼禁用碰撞檢測? - UWA問答: 侑虎科技官方問答社區?

answer.uwa4d.com圖標

今天的分享就到這裡。當然,生有涯而知無涯。在漫漫的開發周期中,您看到的這些問題也許都只是冰山一角,我們早已在UWA問答網站上準備了更多的技術話題等你一起來探索和分享。歡迎熱愛進步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之「石」,也能攻你之「玉」。

官網:www.uwa4d.com

官方技術博客:blog.uwa4d.com

官方問答社區:answer.uwa4d.com

官方技術QQ群:465082844(僅限技術交流)

封面圖片來自網路


推薦閱讀:

分類伺服器是否會是未來伺服器發展趨勢?
十大好玩的BT手游熱門榜
從端游到手游,從大叔到零零後

TAG:遊戲從業者 |