前言
最近出於興趣想自己做一個2D的游戲,因為有着C#的基礎,所以決定使用Unity3D來做。
之前對於Unity3D其實了解不多,不過看了一些Unity3D的視頻和官方文檔后,暫時做起來也沒遇到什么太大的困難。
本篇博客要說的是Unity 2018.3新增的一個東西——Isometric TileMap,一般用於做一個2.5D的地圖。
這個東西官方文檔講的並不詳細,並且有些配置完全沒有說出來,導致始終無法達到預期效果。
國內的各種中文社區和問答網站都沒有這方面的資料,最后還是在Unity的英文社區找到了一篇答案才有了進展:參考鏈接。
但是即使按照這篇答案中的方法進行操作,在我這里依然沒法成功實現這個2.5D的地圖。
后來自己慢慢摸索才最終實現,所以特此記錄下實現的步驟。
導入圖片生成紋理圖片
如果將使用TileMap畫地圖比作給牆貼瓷磚,那么首先我們需要為瓷磚設置不同的花紋,所以我們要導入一張圖片作為花紋。
導入圖片生成紋理圖片后,需要將其紋理類型設置為Sprite (2D and UI),因為Tilemaps不支持其它的紋理類型。
注意到紋理屬性中的Pixels Per Unit (PPU),它的值默認為100。
這個屬性很關鍵,它決定了這個紋理圖片在Unity中顯示時,1個Unity的單元顯示多少個像素。
也就是說一張400 X 200的紋理圖片在Unity中,相當於4*2個Unity單元。
新建瓷磚
紋理就是一個花紋,不可能將花紋直接花在牆上,我們需要根據花紋生成不同的瓷磚,然后再將瓷磚貼到牆上,Tile就是我們的瓷磚。
通過Assets > Create > Tile生成一個Tile文件,然后將之前導入的紋理圖片與Tile文件關聯。
新建Isometric Tilemap
要貼瓷磚還需要一面牆,而Isometric Tilemap就是我們的牆。
使用GameObject > 2D Object > Tilemap,創建一個帶有一個Tilemap子節點的Grid對象。
在這個Grid對象的屬性Cell Layout中,我們發現關於Isometric Tilemap有兩個選項,一個是Isometric,而另外一個是Isometric Z As Y。
Isometric實現的是相當於一個地形一樣的東西,但是想要在這個地形上放上房子和樹木之類的,那么需要設置為Isometric Z As Y。
在這里我們看到還有一個Cell Size的設置,我在這里設置為 X:1,Y:0.5,Z:1。(請注意,這里的Z的大小務必為1,否則同樣無法在地形上放置房子)
Cell Size中的X為1,表示一個Unity的單元格中X的長度相當於多少個Unity單元。
導入一張400 X 200的紋理圖片,它的PPU為100,那么相當於需要4 X 2的Unity單元。
因為我們這里講CellSize的X與Y設置為1和0.5,所以這張紋理圖片在TileMap中的顯示占4個單元格。
而對於Grid下的Tilemap對象,我們只需要修改一個屬性,即將Tilemap Render的Mode改為Individual。
這么做的原因是只有在Individual下,Scene視圖中Tilemap的各個Tile間才能正確排序。
如果是Chunk模式,不同的Tile在繪制時會出現下面這種遮擋的現象:
不過在我們打包時,還是需要將Mode改為Chunk,因為Chunk會按位置對Tiles進行分組,並將它們的Sprite一起批處理以進行渲染,這樣會提高性能。
另外在Chunk模式下,還需要將不同的Sprite放到一個Sprite Altas中,這樣它們才能正確排序。
因為這篇博客的主題不是這方面所以只是捎帶提起,具體如何使用Chunk模式可以查詢官方文檔,這里不再贅述,先將Mode設置為Individual即可。
新建Tile Palette
有了瓷磚和牆,那么我們還需要一個裝瓷磚的箱子。
這個瓷磚箱裝着各種各樣的瓷磚,當我們貼瓷磚時,就從這個瓷磚箱中取出來用。
Tile Palette就是我們瓷磚箱。
使用Window > 2D > Tile Palette,打開Tile Palette視圖。
點擊Create New Palette創建一個Tile Palette,請保證這個Tile Palette的屬性和Isometric Tilemap的屬性匹配,即:
- Cell Size為Manuel,值為 X:1,Y:0.5,Z:1
- Grid為Isometric Z As Y
如果你的圖片是矩形圖片那么就是,那么這里的Y為0.5,如果基於等距投射的圖片,那么Y為0.57735。
創建了Tile Palette后,我們將之前導入的Tile文件拖動到Tile Palette上,也就相當於將瓷磚放到了瓷磚箱中。
如果拖動紋理圖片到Tile Palette上,也會自動生成一個Tile文件,這樣方便得多。
開始繪制Tilemap
貼瓷磚就是從瓷磚箱中選擇瓷磚,然后貼到牆上。
而繪制地圖,就是在Tile Palette中選擇不同的Tile,然后選定Active Tilemap為指定的TileMap后就可以繪制了。
但是當我們准備畫圖的時候發現,一個Unity單元格實在太小了,就相當於一個像素那么大。
這里可以通過設置TileMap對象的scale,將其X和Y放大100倍來處理。(當然也可以通過同時調節Grid的Cell Size的X為100,Y為50,然后再將圖片的PPU從100改為1)
此時可以看到我們的Tile大小正好合適。
那么我們可以在兩個單元格內繪制不同的Tile,但是這里注意到,Tile之間的遮擋存在問題。
解決Tile間的遮擋問題
上面Tile間的遮擋問題,我通過之前提到的Unity英文社區的參考鏈接解決了。
操作就是通過Edit > Settings > Graphics,修改Transparency Sort Mode為Custom Axis,並將其值設為X:0,Y:1,Z:-0.49。
不同Z Position下Tile的繪制
上面我們實現了基本地形的繪制,現在我們需要在地形上面繪制房子。
之前我們繪制Tile時,Tile Palette的Z Position為0。
現在我們需要在地形上繪制房子,那么就需要調高Z Position,將Z Position設為1。
繪制后發現遮擋順序不對,咱們的Z Position為1的房子竟然被Z Position為0的地形給遮擋了。
到這里參考之前的帖子也沒辦法處理這個事,沒有任何文檔和資料有關於這個事情的處理。
我這里也糾結了很久,搞了一兩個晚上都沒搞出來,最后直接加了幾個QQ群,把問題甩在那里,然后打Dota2去了。
而果然指望別人也不怎么靠譜,結果最后還是自己去研究。
雖然不清楚內部工作原理,但是按照排除法去想了一下相關的幾個設置點,問題應該就是出現在透明度排序那里。
於是調節XYZ這三個值,發現將Z進一步調小到-26后就沒有問題了,雖然不知道發生了什么,但是終究是搞定了。
以下是最終效果:
總結
不知道為什么最后一個那么大的坑在官方文檔上完全沒有提及,而且這個功能從這個角度來看,不像是完全做完了的樣子。
希望我的這篇博客對后來的趟坑者有用吧,當然如果有用也別忘了點個贊。
如文中有謬誤,還望不吝賜教。