Ⅰ unity開放世界大地圖如何優化
大地形數據載入方案
大地形載入考慮到現有的內存機制, 不可能一次性將其加入到內存中,這個問題是顯而易見的,其實在游戲開發中經常遇到,比如我們常見的進度條,載入進度條的目的就是等待程序載入場景,進度條只是一個蒙板遮罩而已。大地形的載入,別無他法,只能用分塊,這個是大方向,因此作為程序來說,要做的事情是如何分塊?塊的大小是多少?這些具體的問題我們要根據需求劃分,比如飛行模擬器塊大小可能就要大一些,因為俯瞰的視角比較大,場景漫遊塊可以小一些等等,下面我們就以游戲的經典之作——魔獸世界地形載入方案為例給讀者先介紹一下它的實現原理,魔獸世界這款游戲實現的就是無縫地圖的拼接,所以非常具有參考價值,先看下圖所示:
魔獸世界是如何實現無限地圖的?其實它也是很多的場景塊拼接而成的,我們通過編輯器分析魔獸世界的地形塊的大小劃分,魔獸世界場景我們稱為MapWorld是由一系列MapTile組成,這些MapTile的大小是1600/3 ≈ 533.33m,而每個MapTile又是由 16x16 個MapChunk組成,由此可以計算出每個MapChunk≈33.33m。再就是每個MapChunk又由9x9+8x8個地形頂點高度,法線,若干貼圖層(一般為4層)組成的地表紋理。魔獸世界地形的大小,在這里我們就不討論了,但它劃分塊的思想我們是可以借鑒的。
繼續分析魔獸世界的分塊方法:它們是根據矩陣的方式進行劃分的,在XZ平面上進行的,每個塊都會包含一定的信息數據的,比如:在XZ(3,3)位置的MapTile,每個MapTile都包含了該tile內使用的貼圖、模型實例等等。所謂模型實例也就是我們的道具,可以理解成相同模型在tile內不同擺放位置、大小、角度的信息,它們都是被保存在二進制文件中的,為了節省文件尺寸,模式實例是通過index模型方式保存的,同頂點索引類似,在每個MapTile裡面還有貼圖信息比如貼圖的名字和UV信息等等。本篇課程的分塊思維方式跟魔獸世界的類似,會在後面的章節中詳細介紹,塊分好了以後,下面就是實現原理了。
實現原理:在任何時刻,程序總是保存著玩家所在的及其周圍的3x3個MapTile,隨著玩家的移動,這些MapTile會被動態更新,新的MapTile被載入以替換被卸載的舊MapTile。為了提高調度效率,魔獸引入了Cache機制,Cache中保存著最多16個MapTile數據。需要載入新的MapTile時,首先會在Cache中查找;卸載的舊MapTile也不會被立刻刪除,而是保存在Cache中以備再次調用。由於一段時間內玩家的活動范圍通常不會有太大變化,這一Cache策略在應用中表現的非常出色,這是無縫地圖的基本原理。地形的動態載入卸載我們會使用多線程去實現,我們會整兩個線程:一個線程專門用於載入地形,另一個線程專門用於卸載或隱藏地形MapTile。讓我們再來回憶一下游戲的經典之作,游戲場景效果如下所示:
本篇課程實現的方法可以使用兩種方式處理塊的載入顯示問題,一種是利用對象池的方式,預先載入分塊地形,根據視距進行檢測判斷顯示那些地塊以及隱藏那些地塊,在這里並不刪掉它們。這樣只需要一個線程就可以。另一種方式是利用多線程,起一個線程專門用於移除卸載不在視線范圍內的地塊,這樣可以提升效率,下面介紹使用多線程的載入方案。
多線程實現大地形載入方案
多線程在PC端游戲中使用的比較多,比如可以起一個線程專門進行資源的載入,游戲伺服器中同樣也會有多線程的使用,下面給讀者介紹多線程實現方案,多線程處理問題就是把所有的載入邏輯放到了新的進程中,和主線程做一些進程間的通信,接受主線程的載入建議,做按需載入,也會自主做一些提前預載入,放進分配的內存,就跟魔獸世界的處理方式一樣,通過進程間的內存共享機制,把載入的地形數據,共享給主進程使用。主游戲進程,永遠只要維護一個很小的內存即可,大量的內存數據,都在另一個進程中處理。這樣就可以優化大地形塊的載入,實現方式如下所示:
首先主線程會先載入九塊地形,主線程只負責維護這九塊地形,無論角色怎麼移動,角色所在的整個區域永遠是九塊地形,如上圖所示的,這九塊可以直接使用主線程載入到內存中,剩下的16塊我們通過另一個線程將其放到緩存中,角色的位置是在已經載入好的九塊地形中間,也就是在A所在的位置。隨著角色的移動,會有新的地形塊加入進來,同時現有的地形塊會被置換出去,這樣一直顯示九塊地形,被置換的地形並不會馬上卸載掉,會根據角色移動情況做預判,它會等主線程通知,按照一定的規則進行卸載地塊和載入地塊。其實這種實現方式就是我們通常所說的雙緩存-多線程技術。實現的效果如下所示:
地形分塊載入完事了後,下面就要考慮地形上面的紋理貼圖問題了,地形的貼圖資源也會佔用大的內存,下面介紹如何載入海量貼圖數據。
大地形海量圖片的載入方案
大地形中的場景圖片非常多,地形中的貼圖至少會有四層,這么多貼圖我們在載入時需要考慮的,我們分塊時也需要考慮這些因素,另外場景中使用的LightMap烘培也是要考慮的問題,為了緩解內存壓力,我們事先會將不同塊中的地形材質以及建築物材質進行打包,先介紹如何分塊載入場景貼圖?它實現方式如下所示:
該思路就是將場景中的貼圖根據我們劃分的塊打成不同的圖集,當然也可以將兩個塊中的貼圖打成一個圖集,圖集大小對於PC端來說,最大是4096,在移動端最大是2048。這個也是為了避免內存頻繁的載入卸載會導致很多內存碎片,不利於後面大內存的分配。在打圖集之前我們需要做點事情就是需要將地形塊中的紋理貼圖與我們的打包圖集之間建立一一對應關系,方便對號入座。因為我們打包的圖集跟實際地形之間不會有任何關系,要確立二者之間的對應關系我們需要在它們中間再整一張索引文件表格,它是連接圖集與實際地形紋理的橋梁,通過我們建的索引文件,我們可以找到實際地形中紋理與圖集紋理之間的對應關系,我們建的索引表格是要載入到內存中的,而我們的圖集是根據載入任務後期才加到內存中的,這就要求我們的索引文件盡可能的少,因為它們是常駐內存的,除了海量圖片的載入,我們還需要處理密集建築的載入。
- 密集建築的載入方案
密集的建築載入,大家試想一下,如果把場景中所有的建築一次性載入到內存中,內存瞬間就會占滿,幀數瞬間下降,這也是為什麼大家在游戲場景中移動時,遇到密集的建築就會卡頓一下的原因。以前處理方式是使用LOD處理,被遮擋的物體使用簡模,這樣也會加大內存的負載效果,如果角色一直在建築物之間來回穿梭,這樣不同LOD模型就需要來回切換,對內存也是一個負擔,效果不理想。這些問題對於程序員面來說必須解決的問題,如何解決呢?很多人想到了合並大Mesh,這種方法行不通的,大網格並不適合做裁剪操作,試想一下,我們合並的網格,如果攝像機只看其一小部分,因為它們是一個整體這樣就需要把他們一起載入到內存中,而實際上我們並不需要這么多模型數據,在合並網格時,在這里也給讀者一個建議,盡量把靠的很近的模型進行合並,避免上述問題發生。其實最有效解決方案還是劃分塊,這個劃分塊可以利用地形劃分的思想進行,它是與地形塊緊密相關的,每個地形塊中的建築物跟隨地形塊一起載入。如果塊中的建築非常密集,這種方法還不能夠完全解決,還需要進一步的處理,就是要加入OC遮擋演算法結合LOD演算法,這樣就可以完全解決我們當前的問題了,這也是本篇課程
要講解的方法,再進一步的優化方法是可以將OC遮擋演算法和LOD演算法放到GPU中計算,這樣效率還會提升,在Siggraph2015發表了一篇文章GPU-Driven Rendering Pipelines,它的思想就是使用GPU進行遮擋裁剪處理,主要分兩個階段,使用的是DX12圖形API,如下圖所示:
它的思想就是第一步先做一個初略的遮擋裁剪列表,而後在此基礎上再根據視線距離或者射線檢測做進一步的細化裁剪操作,這個思想跟我們的碰撞檢測演算法類似,引擎中碰撞檢測演算法也是基於這個原理實現的,給讀者介紹一下:實際可用的碰撞檢測演算法,一般要分2個階段:
第一階段,broad phase 快速找出潛在的碰撞物體對列表,不在這個列表裡的是絕對沒可能碰撞的。broad phase確定了一批需要進一步檢查的物體對。
第二階段,narrow phase 准確找出發生碰撞的物體對列表。因為上一個階段的部分物體對實際上是沒有碰撞的,需要在這個階段剔除。
broad phase其中有一個簡單演算法叫sweep and prune(SAP),本質上是利用了排序演算法。第一步是初始化排序列表,列表中的元素是包圍盒,可以用任意排序演算法完成,例如快排;之後的排序就不是用快排了,而是用冒泡排序,為什麼用冒泡排序更好呢?是因為一個默認的前提:物體的運動有時間相關性(temporal coherence),即當前幀和下一幀的位置是相近的,所以在冒泡排序過程中,發生的位置交換預期都很靠近。
其實演算法中有很多類似的地方,這里我們也要互相借鑒它們解決問題的思想用於解決我們的問題。筆者以前做的是端游,端游中很多優化思想同樣適用於移動端,移動端跟PC端比,就是一台配置比較低的電腦而已。接著我們的遮擋裁剪繼續給讀者介紹,論文作者也做了一個效率測試,以250』000物體,1G的網格為例,測試效果如下所示:
是不是很酷啊!在項目開發中完全可以用它解決問題,下面我們再談談使用GPU去優化我們的大地形場景。
GPU大地形渲染優化解決方案
我們的大地形首先會有自己的地表貼圖,常用的地表貼圖是四張紋理融合,最多可以有八張貼圖融合,地形紋理渲染會涉及到LOD演算法,遠處的地形網格可以簡化一些,對應的貼圖也是最低的,這就是MipMap的使用。另外肯定有草有花以及其他大量相同的物件渲染,先說說草和花的繪制,他們在游戲中會非常的多,常用的做法是引擎提供的面片或者是十字交叉,或者三張圖片交叉,然後將帶有Alpha通道的貼圖映射在上面,如下圖所示效果:
CPU繪制這些草或者花在PC端是可以的,因為現在的電腦都是多核的,在手機端就會影響到效率問題了。使用CPU繪制,DrawCall會非常的多,而且草或者花還需要擺動,計算量很大的,這嚴重影響了運行效率,CPU有難,GPU可以幫忙,我們可以將草或者花的繪制放到GPU中執行,效果如下所示:
Ⅱ unity3d樹種多了怎麼優化
針對你的問題簡單介紹一下,
我默認以為你說的種樹的行為是發生在terrain上面哈,說到優化正常情況下分兩個方面說
如果是移動平台我們不會用真的terrain進行展示,terrain本身就是一個超大的資源消耗,移動平台一般用低面數模型也就是做好的地形模型進行取代,相應的樹木和草這些東西在移動平台都是非常奢侈的存在,一般都是用很普通的貼圖插在山體模型上面,當然比如現在流行的手機版本的吃雞游戲他們也用了低面數或者是比較簡陋的樹木模型。
如果是pc平台,我本以為pc就是一個要展示的盡善盡美的地方,現在硬體成本越來越低,很少人考慮優化了,但是也不是沒有,基礎來說,前期烘焙就可以很大一方面解決dc過高的問題,這個移動平台也是同樣適用的,但是說烘焙聽起來簡單,但部分人都轟毀了,算是一個有調教技術的活,調多了才比較敏感吧,所以一個lighting面板就夠學好一陣子了,樹木方面沒什麼好說的lod的模型首選,配合鏡頭的culling可以分級渲染,這里說的比較籠統就是,fog的加入也是一個不錯的選擇,這些都要看你到底真的是種了多少樹,樹木多地形大,可以考慮把地形都steam化,這個可以依賴目前現成的插件幫助,但是個人認為要做這樣史詩級的大畫面還在意用戶會帶不動么?哈哈。
Ⅲ 如何用unity3D對游戲運行性能進行優化
大家在玩游戲的時候可能經常會遇到卡頓,延遲,死機,不流暢等等問題,那麼這些問題是怎麼引起的呢?如何去盡量的減少這些情況的發生呢?這些問題對於游戲開發者來說是必須要面對的問題, 也是必須要解決的問題。
上面我們例舉在游戲運行的過程中可能會遇到的一些問題, 每種問題引起的原因有很多多,但是我們可以從大方向對整體游戲進行優化,使游戲整體性能更優,從而減少這些情況的發生。對於性能優化我們大體可以從四個大方向去優化,即:CPU,GPU, 內存以及網路和IO,下面給大家一一講解:
GPU優化,GPU的職責就是負責游戲中所有的圖像、特效的渲染。GPU的消耗過高會導致游戲畫面卡頓、畫質降低、手機發熱等情況,嚴重影響游戲體驗。對於游戲來講這是致命的。關於CPU優化大家可以從以下幾方面入手:
1、資源優化,比如合理規劃圖集,指定合理的粒子效果,約定模型的三角面數
2、簡化著色器,使用多級紋理與材質貼圖技術相結合
3、使用LOD技術、遮擋剔除等技術,減少GPU繪制的數量
4、針對不同的系統平台使用對應的壓縮格式。
5、優化顯存帶寬
游戲渲染可以說是游戲的心臟,所以GPU的優化顯得尤為重要,需要開發者格外的重視
內存優化,內存的功能我就不多介紹了, 相信大家都了解。由於內存不足所導致的問題有閃退,卡死等。對於內存的優化,一是降低資源的大小,比如剔除不需要的資源、對資源進行壓縮等;二是及時動態的載入和卸載資源,這樣可以大大的減少瞬時內存的壓力,減少因內存浪費而給游戲帶來不必要的消耗。三是降低資源的質量,這是一種有損的優化,不到最後一般不用,當然我們也可以根據不同的設備使用不同質量的資源,將損失降到最低。
網路和IO優化, 他們主要負責資源的載入, 可能是網路的或者本地的。網路不好,或者資源載入時間過長會讓大大降低用戶體驗。因此在CPU、GPU、內存優化後我們同時也不能忽略網路與IO優化,對於網路與IO的優化,大家可以從以下幾方面入手:
1、限制短時間內的發包率
2、合理優化包大小,減少包的冗餘數據,降低網路請求次數
3、對回包進行分幀處理,及時響應
4、使用獨立線程、協程等手段優化資源載入。
Ⅳ 使用unity3d開發的手游安裝包比較大,如何優化
解決方法有三種:
一:優化圖片、資源,壓縮安裝包體積,犧牲一部分手游品質減小安裝包體積,這也是比較常見的一種方法;
二:分包技術,資源切割,分段下載,進入游戲前進行二次下載。
三:愛加密的手游壓縮技術,通過拆分資源,在保障了游戲品質和游戲體驗流暢的情況下,實現資源後台自動載入,最高可以壓縮80%。
以上三種解決方法中,愛加密的手游壓縮技術是比較完美的一種,既沒有影響游戲品質,又可以完美分包,不用二次下載,保障了良好的用戶體驗。