由unity引擎做的遊戲《缺氧》,它的地圖的機制是怎麼實現的?

如圖,類似泰拉瑞亞.

①可以以方塊為單位破壞地形.

②許多相同方塊相連構成一個整體使用無縫的貼圖.

這樣看著很舒服不單調,想知道其中的原理,國內unity2D教程太少,翻牆毫無結果,於是來請教.


有個老外對於解剖泰拉瑞亞做了很多出色工作,這是他的博客

地形編輯器 Terrafirma - Mapping for Terraria

地表貼圖uv分布 http://seancode.com/terrafirma/uvs.html

wld文件格式解析 http://seancode.com/terrafirma/world.html

github倉庫 mrkite/TerraFirma


terraria我也很喜歡,用unity做過類似他的demo,可以給你分享分享voxel 2d的一些心得:

1)tile 的定義

一般相同類型的tile都有多種,比如泥土地,可能有7-8中,每種周圍可以憑藉的方式也有很多種,還有泥土和草地,砂岩的拼接過渡tile,tile美術需要保證拼接是無縫的,然後就是有一種數據定義,用於定義什麼tile可以和其他tile拼接,每個tile一般有8個方向,邊緣的tile少1-2條邊;

2)在unity里渲染

如果只是做demo,我推薦使用Mesh,基於一個chunk填充頂點數據,一個chunk大概16x16個tile,每個tile 16x16 像素 把所有tile合併進入一個貼圖,減少批次,這裡有一個技巧是,數據的準備可以多線程,最後在Mesh數據賦值是在主線程,可以分幀做,在快速移動相機時會很平滑,準備用的數據可以緩存,避免gc alloc;

如果做遊戲,仔細優化,這部分我推薦做到low level render plugin里,完全在c代碼里做,沒有gc,快速計算tile;

如果是unity5.5以後,也可以考慮command buffer來做;

像terraria那樣,需要大概5*5個tile或者7x7,隨著相機移動,動態刪除、創建新的chunk。

3)挖、補

挖、補去一個tile的時候,需要重新計算tile周圍的填充,及計算新的頂點數據和uv

4)其他方面

流體,流體是terraira比較有意思的地方,困難的地方還是計算,我之前也是多線程計算才能效率比較高,否則非常影響渲染效率;

隨機世界構建,這個經驗不多,當初也沒實現,這裡我感覺是一些2d連續隨機數+一些模式填充。

ps,terraria是c#寫得,被人decompile,很多代碼可以參考,csnxs/Terraria


最近寫遊戲涉及到了板塊地圖的繪製,正好來答一下

板塊地圖繪製的原理跟unity沒什麼關係

《缺氧》和《Terraria》的地圖渲染方式還是有一點不一樣的,我來解釋一下(以下稱「tile」為「塊」

每個塊所使用的貼圖都是與相關貼圖無縫銜接的,如:

拼接起來是醬嬸的:

在地形生成後,對於每個塊都要檢測一次「鄰居塊」 (即該塊周圍八個方向上的塊),來確定自己所處的邊緣,記入自己的屬性,渲染時再繪製對應的貼圖

當添加或刪除地圖塊時,也要對自身以及鄰居地圖塊都要進行一次邊緣檢測來更新邊緣屬性

舉個例子,從一個塊的西北方順時針進行檢測,用「1」和「0」來代替泥土塊的存在與否

檢查結果為:11100011,就可以確定該塊的貼圖為

《Terraria》就是用類似上面介紹的方式來繪製地圖

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

而在《缺氧》中,鄰居塊檢測的結果只用於確定岩石塊的不規則邊緣的形狀,然後對相同類型的岩石塊用無縫銜接的大貼圖以平鋪的方式 blit 到區域內,有點類似於蒙版

用之前的例子表示就是:

最後就變成了

以上,biu~


無縫拼接,之前偶然看見的一個基礎版

《C++遊戲開發》筆記十三 平滑過渡的戰爭迷霧(一) 原理:Warcraft3地形拼接演算法


有人說了自動選取合適的tile來拼接。用的是這種 tile 。圖源自 RPG Maker。RPG Maker 里就有這種功能,那裡面叫 autotile。你裝個 RPG Maker 試試就明白了。其實挺簡單的。

這裡面每個小格是16*16的,遊戲中實際的tile是32*32的,是這裡面四個小格拼成的。為了保證無縫,圖案是每兩個小格一循環。

如果讓變化更豐富,可以對其中一些格子做變種,然後從變種里隨機選取。


根據周邊tile狀態更換當前tile貼圖,也就是說同種tile也需要做許多種可能的貼圖,這種在中古時期的遊戲中應用很多,甚至包括魔獸爭霸。

具體遊戲分析的話,格子的銜接統一採用了一個mask圖片,可以看到按384切分成了多個狀態的格子,根據生成地圖格子中的同類銜接狀態值選擇mask切片,然後與原始的四方連續貼圖融合即可。

另外格子種類的顯示層級是固定的,比如沙土大於氧氣等,那麼整體銜接起來就會比較舒服了,而且只需要一個mask即可作為通用銜接圖。

可參考我一篇分析,瓷磚貼圖的過度

http://www.zhust.com/index.php/2016/10/關於瓷磚貼圖的過渡(tile)/


無非就是用離散數據表示,然後渲染的時候渲染成連續


推薦閱讀:

unity中從Resources下讀取較大的資源會卡,有解決辦法么?
如何評價雲風與xlua作者關於unity,c#,lua的討論,以及他後來給出的方案?
mipmap的優點具體是什麼?
Unity程序員如何轉變為技術美術?現已熟悉UnityShaderlab.?
Unity工作一年能力應該到達什麼水平?

TAG:Unity遊戲引擎 | 2D遊戲 | 泰拉瑞亞Terraria | 缺氧OxygenNotIncluded |