最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

HexMap學(xué)習(xí)筆記(五)——更大的地圖

2019-03-14 11:43 作者:皮皮關(guān)做游戲  | 我要投稿

作者:沈琰


前言

這篇教程為地圖添加了更多的編輯功能,是其更像一個(gè)六邊形地圖編輯器了。代碼與操作均不難,簡單過一遍就行。

本篇原文地址:https://catlikecoding.com/unity/tutorials/hex-map/part-5/



本篇難度:★☆☆☆☆

這個(gè)教程是HexMap系列的第五篇,之前都是在一張很小的地圖上進(jìn)行編輯,這次將會把地圖放大一些。

1.地圖網(wǎng)格塊

我們不能把地圖網(wǎng)格設(shè)置地太大,因?yàn)閱蝹€(gè)mesh的容量是有限的(注:Unity中Mesh數(shù)組最大能存儲65000個(gè)頂點(diǎn))。解決方案是使用多個(gè)mesh拼接,這樣就能把網(wǎng)格分成若干塊,這里將使用一個(gè)固定大小的矩形塊。

把網(wǎng)格分為三乘三大小的網(wǎng)格塊的樣子

先設(shè)置網(wǎng)格塊塊的大小為五乘五,所以每一個(gè)網(wǎng)格塊是25個(gè)單元格,在HexMetrics里定義。

網(wǎng)格塊的大小設(shè)置成多大比較合適?
視情況而定,較大的網(wǎng)格塊意味著數(shù)量少但較大的mesh,這會使draw calls較少。但是較小的網(wǎng)格塊會在視錐體裁剪剔除時(shí)效率較高,繪制的三角形較少。實(shí)際方法就是先設(shè)置一個(gè)預(yù)估的大小然后再進(jìn)行微調(diào)。

現(xiàn)在我們不能再使用網(wǎng)格本身的尺寸,而是用網(wǎng)格塊的倍數(shù)的尺寸。修改HexGrid讓其以塊的形式定義網(wǎng)格的大小。默認(rèn)先設(shè)置為4乘3個(gè)網(wǎng)格塊,這樣就是12個(gè)網(wǎng)格塊和300個(gè)單元格,這對于地圖測試是個(gè)較為合適的大小。

我們?nèi)匀灰褂脀idth和height這兩個(gè)變量,但它們應(yīng)該變成私有類型。然后重命名為cellCountX和cellCountZ。使用IDE的快捷功能可以一次重命名所有出現(xiàn)這些變量的位置。這樣在處理地圖塊或者單元格的個(gè)數(shù)時(shí)就會很清楚。

指定地圖塊的尺寸

修改Awake方法,這樣在需要它之前單元格的數(shù)量就能用地圖塊的數(shù)量推算出來。把單元格的創(chuàng)建放到它們自己的方法中,讓Awake保持整潔。


1.1 地圖塊預(yù)制體

我們需要一個(gè)新的組件腳本來表示地圖塊。

接下來創(chuàng)建一個(gè)地圖塊的預(yù)制體,復(fù)制HexGrid對象并重命名為HexGridChunk。刪除上面的HexGrid腳本并用HexGridChunk代替,然后把其創(chuàng)建為預(yù)制體并在場景中刪除。

地圖塊的預(yù)制體,與其自己的畫布組件和HexMesh對象

因?yàn)橐贖exGrid里實(shí)例化這些網(wǎng)格塊,給其預(yù)制體一個(gè)引用。

添加地圖塊的字段

地圖塊的實(shí)例化看起來很像是單元格的實(shí)例化,為之后方便使用,用數(shù)組把它們存起來并用雙重循環(huán)去填充。

HexGridChunk里的實(shí)例化與之前實(shí)例化六邊形網(wǎng)格相似,在Awake里設(shè)置數(shù)據(jù)并在Start里三角化。它需要canvas和mesh的引用和一個(gè)存儲自身單元格的數(shù)組。不過這里并不會創(chuàng)建單元格,仍然把創(chuàng)建步驟放在HexGrid中完成。

.3 把單元格賦值到地圖塊中

HexGrid仍然負(fù)責(zé)創(chuàng)建所有的單元格,這是對的。現(xiàn)在要做的是添加單元格到它所連接的地圖塊中,而不是設(shè)置它們的mesh和canvas。

我們可以通過對X和Z按地圖塊的尺寸進(jìn)行整數(shù)分割來找到正確的地圖塊。

通過整數(shù)結(jié)果還可以確認(rèn)每個(gè)單元格在其所在地圖塊中的下標(biāo),有了這個(gè)下標(biāo)就可以把單元格添加到地圖塊中。

之后HexGridChunk.AddCell就可以把單元格放到它自己的數(shù)組里,再設(shè)置單元格和其UI的父節(jié)點(diǎn)。

1.3 清理代碼

現(xiàn)在HexGrid能清除掉它的canvas和mesh子物體對象,還有與之相關(guān)的代碼。

因?yàn)槲覀儎h除了Refresh方法.現(xiàn)在HexMapEditor不能再使用它了。

清理后的HexGrid

當(dāng)點(diǎn)擊運(yùn)行后,地圖看起來一樣,但是場景內(nèi)對象的層級會發(fā)生改變。HexGrid現(xiàn)在會生成地圖塊的子物體,包含其單元格連同mesh和canvas。

運(yùn)行模式下的地圖塊子物體

單元格的坐標(biāo)顯示標(biāo)簽有點(diǎn)問題:我們一開始設(shè)置的標(biāo)簽寬度是5,這足夠顯示兩個(gè)字符。在較小的地圖上剛好用完,但現(xiàn)在我們可以獲取到“-10”這樣有三個(gè)字符的坐標(biāo),這樣一來字符無法相匹配并有斷層。把標(biāo)簽的寬度增加到10或更多來解決這個(gè)問題。

更寬一些的單元格標(biāo)簽

現(xiàn)在我們能創(chuàng)建大得多的地圖!當(dāng)開始生成整個(gè)網(wǎng)格地圖時(shí),如果地圖較大可能會花上一點(diǎn)時(shí)間。但當(dāng)一次完成之后,你就有更大的 區(qū)域可以玩了。


1.4修復(fù)編輯功能

現(xiàn)在地圖編輯功能用不了,因?yàn)榫W(wǎng)格的刷新方法刪除了。現(xiàn)在需要刷新的是單獨(dú)的地圖塊,所以在HexGridChunk里添加Refresh方法。

那應(yīng)該在什么時(shí)候調(diào)用這個(gè)方法?之前是每時(shí)每刻都在刷新,因?yàn)槟菚r(shí)只有一個(gè)mesh,但現(xiàn)在我們有很多的地圖塊,就不能每個(gè)地圖塊都一直刷新,僅當(dāng)?shù)貓D塊被改變時(shí)再刷新效率會更高,否則編輯較大地圖時(shí)會感覺很卡。

那問題就變成了如何知道哪個(gè)地圖塊需要刷新。一個(gè)比較簡單的方法是確保每個(gè)單元格都知道它是屬于哪一個(gè)地圖塊,這樣單元格就能在其被改變時(shí)刷新它所在的地圖塊,所以給HexCell一個(gè)地圖塊的引用。

當(dāng)添加單元格時(shí)HexGridChunk可以直接把自己賦值給它。

當(dāng)這些連接建立之后,在HexCell里創(chuàng)建一個(gè)Refresh方法,單元格刷新時(shí)就同步刷新自己所在的地圖塊。

我們不需要把HexCell.Refresh()設(shè)置成公共方法,因?yàn)橹挥袉卧褡约呵宄裁磿r(shí)候發(fā)生了變化。例如,在高度改變之后。

實(shí)際上只有在高度被設(shè)置成了一個(gè)不同的值時(shí)才需要刷新,甚至都不需要在賦了一個(gè)相同的高度值后重新計(jì)算,所以這種情況下可以在set屬性的一開始就跳出。

然而這會跳過第一次設(shè)置高度為0時(shí)的計(jì)算,因?yàn)?是網(wǎng)格的默認(rèn)高度,為預(yù)防這一點(diǎn),確保初始值是你永遠(yuǎn)都不會用到的值。

什么是int.MinValue?
這是int所能表示的最小值,在C#中int是一個(gè)32位的數(shù)字,它有2的32次方種可能的整數(shù)值,分成正值和負(fù)值和0,其中一位用來指出這個(gè)值是不是負(fù)的。
最小值是負(fù)的2的31次方=-2147483648,我們永遠(yuǎn)不會使用這個(gè)高度等級。
最大值是2的31次方減1=2147483647,比2的31次方少1是因?yàn)檫€有0存在。

為了檢測顏色是否被改變,我們也要把顏色變成一個(gè)屬性。重命名成首字母大寫的Color,接著改成屬性并使用私有的color變量。顏色的默認(rèn)值是標(biāo)準(zhǔn)黑色,就這個(gè)不用改了。

在運(yùn)行模式下會報(bào)空引用異常,這是因?yàn)樵诎褑卧褓x值給它所在的地圖塊之前就設(shè)置了默認(rèn)的顏色和高度。最好的辦法是在這里先不刷新,因?yàn)槲覀儠诔跏蓟瓿芍笕腔鼈儭Q句話說就是只有在地圖塊被賦值完成后才進(jìn)行刷新。

現(xiàn)在又能編輯地圖了!然而還是有個(gè)問題,這似乎會在跨越地圖塊邊界編輯顏色時(shí)出現(xiàn)。

地圖塊邊界之間出現(xiàn)了問題

這個(gè)問題很好理解,因?yàn)橐粋€(gè)單元格發(fā)生變化后所有它連接的相鄰單元格也會發(fā)生改變,而這些相鄰單元格有可能在不同的地圖塊中。最簡單的解決方案是當(dāng)單元格與其相鄰單元格不在一個(gè)地圖塊是也刷新一下相鄰單元格的地圖塊。

這雖然可行,但我們要刷新單個(gè)地圖塊多次,一旦我們在一次繪制橫跨多個(gè)單元格時(shí),情況就更糟糕了。

我們沒必要在地圖塊刷新信息時(shí)直接三角化,我們可以通知這個(gè)地圖塊需要刷新,然后在編輯完成時(shí)一次性三角化。

因?yàn)镠exGridChunk沒有用來做其它的事情,我們可以用腳本的enable狀態(tài)作為需要刷新的信號,當(dāng)開始刷新時(shí),給腳本設(shè)置enable狀態(tài),就算多次設(shè)置也沒關(guān)系,不會有變化。稍后腳本更新時(shí),我們就在這里進(jìn)行三角化,然后再次設(shè)置狀態(tài)為disable。

我們使用LateUpdate代替Update,這樣就能確保三角化發(fā)生在當(dāng)前幀編輯完成之后。

Update與LateUpdate有什么區(qū)別?
每一幀中, 所有enabled狀態(tài)的組件中的update會在隨機(jī)時(shí)候調(diào)用.在這結(jié)束之后,LateUpdate方法也是同樣的邏輯.所以這是兩個(gè)更新步驟,一個(gè)早一些一個(gè)晚一些。

因?yàn)槟_本組件默認(rèn)狀態(tài)就是enabled,所以我們不再需要在Start里三角化,現(xiàn)在就能刪了這個(gè)方法。

20乘20的地圖塊尺寸,包含10000個(gè)單元格


1.5 共享列表

盡管現(xiàn)在三角化網(wǎng)格地圖的方式有了較大的改變,但HexMesh里的工作還是一樣的,它只需要一個(gè)單元格數(shù)組就能干活,無論是一個(gè)還是多個(gè)mesh都沒有關(guān)系。之前我們都沒有考慮過使用多個(gè)mesh,或許這里能有優(yōu)化的地方?

HexMesh里使用的列表實(shí)際上是一個(gè)臨時(shí)數(shù)據(jù)緩存,它只在三角化的過程中使用。然而現(xiàn)在地圖塊的三角化也是一次性完成的,所以還是只需要設(shè)置一次列表的數(shù)據(jù)而不是每個(gè)mesh三角化時(shí)都設(shè)置一次,我們可以把列表設(shè)置為靜態(tài)類型來實(shí)現(xiàn)這個(gè)改動(dòng)。

使用靜態(tài)類型的列表會有很大的效率提升么?
這只是一個(gè)說明該如何使用列表的簡單改動(dòng),雖然提升不大但值得這么去做,即使我們現(xiàn)在不用太過擔(dān)心它的效率問題。
這樣改動(dòng)后效率會有些微提升,因?yàn)榱斜砉蚕硪院笏枰膬?nèi)存分配要少上一些。當(dāng)使用20乘20的地圖塊時(shí),節(jié)省的內(nèi)存差不多剛超過100MB。


2.攝像機(jī)控制

地圖變大是件好事,但是有的地方看不見就很捉急。為了能看到整張地圖的全貌,需要攝像機(jī)能夠四處移動(dòng),焦距變化功能也應(yīng)該是必須的。接下來就實(shí)現(xiàn)一個(gè)有這些功能的相機(jī)。

新建一個(gè)空對象命名為HexMapCamera,重置它的transform組件。為其新建一個(gè)子對象并命名為Swivel,然后在Swivel下創(chuàng)建一個(gè)子對象Sticlk。把主相機(jī)設(shè)置為Stick的子物體,然后重置其transform組件。

攝像機(jī)的層級

Swivel的工作時(shí)控制攝像機(jī)看向的角度,把它的默認(rèn)旋轉(zhuǎn)設(shè)置為(45,0,0)。Stick則是用來控制攝像機(jī)的遠(yuǎn)近,設(shè)置默認(rèn)坐標(biāo)為(0,0,-45)。

現(xiàn)在我們需要一個(gè)腳本來控制這個(gè)組合裝置,在根節(jié)點(diǎn)添加這個(gè)腳本并添加Swivel和Stick的引用,在Awake的時(shí)候獲取它們。

攝像機(jī)的腳本

2.1 攝像機(jī)遠(yuǎn)近控制

第一個(gè)要實(shí)現(xiàn)的功能就是攝像機(jī)的遠(yuǎn)近視距變化,我們可以用一個(gè)float變量記錄當(dāng)前的視距,值為0表示相機(jī)拉到最遠(yuǎn),值為1表示相機(jī)拉到最近,把初始值設(shè)為1即最近。

攝像機(jī)變距功能通常都是用鼠標(biāo)滾輪或者類似的輸入方法控制,我們可以使用Unity默認(rèn)的MouseScrollWheel輸入軸,然后在Update方法里檢查是否有輸入增量,如果有再調(diào)用方法調(diào)整視距。

要調(diào)整視距幅度就簡單的加上輸入增量,然后將值限制在0-1之間。

當(dāng)我們改變視距的值時(shí),攝像機(jī)的距離也應(yīng)該相應(yīng)的改變,可以通過調(diào)整Stick的Z軸坐標(biāo)來實(shí)現(xiàn)。添加兩個(gè)公共類型的float變量,設(shè)置Stick的最大和最小距離。由于我們創(chuàng)建的地圖相對較小,先暫時(shí)設(shè)置為-250和-45。

視距改變之后,應(yīng)該基于這個(gè)新的視距線性插值計(jì)算這兩個(gè)值,然后更新Stick的位置。

現(xiàn)在能調(diào)整了,但還不太好用。通常游戲中的攝像機(jī)會在焦距拉遠(yuǎn)的時(shí)候過渡到從上至下的俯視角。我們可以用過旋轉(zhuǎn)Swivel來實(shí)現(xiàn),所以也同樣為Swivel添加最大和最小的旋轉(zhuǎn)角度標(biāo)量,默認(rèn)設(shè)置為90和45。

就像計(jì)算Stick的坐標(biāo)一樣,插值計(jì)算出合適的攝像機(jī)角度,然后給Swivel的旋轉(zhuǎn)賦值。

Swivel的最小值和最大值

可以通過調(diào)整鼠標(biāo)滾輪的靈敏度設(shè)置來調(diào)整視距的變化速度,在Edit/ProjectSettings/Input里可以找到,例如可以把靈敏度默認(rèn)值0.1改為0.025來獲得更為平滑的視距變化感覺。

2.2 攝像機(jī)移動(dòng)

下一步是攝像機(jī)的移動(dòng),我們要在Update中檢測X和Z方向的移動(dòng)。和調(diào)整視距類似,可以使用默認(rèn)的水平和垂直的輸入軸,這允許我們用WASD和方向鍵來移動(dòng)攝像機(jī)。

最直接的方法是獲取攝像機(jī)當(dāng)前的坐標(biāo),加上X和Z軸上的輸入增量,然后將結(jié)果賦值到攝像機(jī)的坐標(biāo)值上。

現(xiàn)在可以按住方向鍵或者WASD來控制攝像機(jī)移動(dòng)了,但速度不是恒定的,它取決于幀率。為了能確定移動(dòng)的距離,需要使用時(shí)間增量以及期望的移動(dòng)速度,所以添加一個(gè)公共類型的變量moveSpeed并設(shè)置為100,接著把他和時(shí)間增量作為變量因素添加到坐標(biāo)的位移增量中。

移動(dòng)速度

現(xiàn)在也能在X或者Z軸上以恒定速度移動(dòng)了,但如果沿著對角線在兩個(gè)方向上同時(shí)移動(dòng)會快一些,所以需要把移動(dòng)速度的向量標(biāo)準(zhǔn)化,當(dāng)做一個(gè)方向來使用。

對角線的速度也修正了,但有點(diǎn)出乎意料的是當(dāng)松開按鍵后相機(jī)依然會持續(xù)移動(dòng)一段時(shí)間。這是因?yàn)檩斎胼S按下按鍵是不會立即跳轉(zhuǎn)到它的極值上,而是會有一個(gè)過渡時(shí)間,松開按鍵時(shí)也是一樣。又因?yàn)槲覀儼演斎氲南蛄繕?biāo)準(zhǔn)化了,所以在這一段時(shí)間內(nèi)一直會維持在最大速度上。

現(xiàn)在我們可以修正輸入設(shè)置去除它的延遲過渡,但是帶來的操作平滑的感覺卻很值得保留,所以我們可以把當(dāng)前輸入的最大值作為移動(dòng)的阻尼系數(shù)。

現(xiàn)在攝像機(jī)的移動(dòng)功能在焦距拉近時(shí)沒什么問題,但當(dāng)拉遠(yuǎn)時(shí)又感覺太慢了,我們需要在攝像機(jī)拉遠(yuǎn)時(shí)提高速度??梢园阎皢蝹€(gè)moveSpeed分成兩個(gè)針對最大和最小焦距的移動(dòng)速度,然后插值計(jì)算它們。先分別設(shè)置為400和100。

根據(jù)視距變化的相機(jī)移動(dòng)速度

現(xiàn)在攝像機(jī)可以在地圖中自如的移動(dòng)了!實(shí)習(xí)上現(xiàn)在能移動(dòng)出地圖的邊界,這并不合理,攝像機(jī)應(yīng)該只能在地圖中移動(dòng)。為修正這個(gè)問題,首先要知道地圖的范圍。所以在腳本中獲取HexGrid的引用。

需要獲取網(wǎng)格的尺寸

實(shí)際上這稍微有點(diǎn)不精確,基準(zhǔn)線應(yīng)該是在單元格的中心而不是左邊,我們希望攝像機(jī)最終會停在右邊單元格的中心上,因此需要在X的最大值上減去半個(gè)單元格寬度。

基于同樣的原因Z的最大值也要減去一些,因?yàn)槎攘繕?biāo)準(zhǔn)有點(diǎn)不一樣,所以這里要減去整個(gè)單元格的寬度。

現(xiàn)在移動(dòng)功能就完成了,除了一個(gè)小細(xì)節(jié)。有的時(shí)候UI會響應(yīng)方向鍵,其結(jié)果就是在移動(dòng)攝像機(jī)的時(shí)候UI上的滑動(dòng)條也會跟著移動(dòng)。當(dāng)你點(diǎn)擊UI并把鼠標(biāo)停留在上面,UI就會認(rèn)為自己處于激活狀態(tài),這時(shí)就會發(fā)生這種情況。

可以取消選擇EventSystem上的Send Navigation Event選項(xiàng)來禁止UI監(jiān)聽按鍵事件。

取消選中Send Navigation event


2.3 攝像機(jī)旋轉(zhuǎn)

想看看山崖后面是什么東西?如果能旋轉(zhuǎn)攝像機(jī)就能很方便的看到!所以同樣要添加這個(gè)功能。

旋轉(zhuǎn)功能與焦距沒有什么關(guān)系,所以定義一個(gè)速度變量就足夠了。添加一個(gè)公共類型變量rotationSpeed并設(shè)置為180。在Update里通過對輸入軸"Rotation"取值來獲取旋轉(zhuǎn)增量,并在需要時(shí)調(diào)整旋轉(zhuǎn)。

旋轉(zhuǎn)速度

事實(shí)上默認(rèn)輸入軸里并沒有"Rotation",我們要自己去創(chuàng)建一個(gè)。在輸入設(shè)置中復(fù)制最上面的"Vertical"然后把名字改成"Rotation",按鍵分別改成Q,E,逗號和點(diǎn)。

自設(shè)的旋轉(zhuǎn)軸
我下載了Unity的工程包,為什么里面沒有這個(gè)input設(shè)置?
輸入設(shè)置是項(xiàng)目范圍的設(shè)置,它不包括在Unity的工程包中。幸運(yùn)地是你很容易自己添加一個(gè),如果沒有添加就會報(bào)一個(gè)輸入軸丟失的異常。

在AdjustRotation里記錄并修正旋轉(zhuǎn)角度,需要進(jìn)行旋轉(zhuǎn)的是包括支架在內(nèi)的整個(gè)攝像機(jī)裝置對象。(即根節(jié)點(diǎn))

因?yàn)樾D(zhuǎn)一整圈是360度,所以限制旋轉(zhuǎn)角的范圍在0-360之間。

旋轉(zhuǎn)操作

旋轉(zhuǎn)功能就完成了,不過當(dāng)你試著轉(zhuǎn)動(dòng)時(shí)你會發(fā)現(xiàn)移動(dòng)方向是基于世界坐標(biāo)系的絕對坐標(biāo)。所以當(dāng)旋轉(zhuǎn)180度之后移動(dòng)方向會與預(yù)期的完全相反,而移動(dòng)方向如果是相對于攝像機(jī)的視角則會更易于使用,所以我們把當(dāng)前攝像機(jī)的旋轉(zhuǎn)與移動(dòng)相乘。

相對自身坐標(biāo)系的移動(dòng)



3.高級編輯功能

現(xiàn)在我們有了更大地圖,是時(shí)候更新一下編輯工具了。一次編輯一個(gè)單元格太過局限了,所以使用更大的筆刷是一個(gè)不錯(cuò)的注意。一次只編輯顏色或者是高度中其中一項(xiàng),而讓其他部分保持不變,這同樣也是一個(gè)很實(shí)用的功能。

3.1顏色和高度可選功能

我們可以通過添加一個(gè)切換(toggle)組來實(shí)現(xiàn)顏色選擇功能。復(fù)制一個(gè)顏色選項(xiàng)卡并將標(biāo)簽名改為“---”或者別的什么能代表這不是一個(gè)可選顏色的字符。然后設(shè)置其OnValueChanged事件傳遞參數(shù)為-1。

無效顏色數(shù)組下標(biāo)

當(dāng)然這對于我們的顏色數(shù)組來說是一個(gè)無效的下標(biāo),我們可與以此確定是否對單元格應(yīng)用顏色修改功能。

高度變化使用的是一個(gè)滑動(dòng)條(Slider)組件,所以我們沒辦法在這里面創(chuàng)建一個(gè)切換開關(guān)。于是用一個(gè)分離的切換選項(xiàng)卡(toggle)表示是否應(yīng)用高度編輯,默認(rèn)設(shè)置為開啟狀態(tài)。

添加這個(gè)新高度開關(guān)到UI上,把所有內(nèi)容都放到一個(gè)新的UI面板上,把高度滑動(dòng)條設(shè)置為水平好讓UI看起來更整潔一些。

為了讓這個(gè)開關(guān)起效,需要一個(gè)新的方法并與UI相關(guān)聯(lián)。

當(dāng)你掛載方法的時(shí)候確保是使用的方法列表頂端的dynamic bool method。正確的版本不會在檢視面板中顯示檢驗(yàn)框。

傳遞高度選中狀態(tài)到選項(xiàng)卡中

現(xiàn)在你可以選擇是修改顏色還是高度,或者像之前一樣同時(shí)修改。甚至可以兩個(gè)都不選,盡管現(xiàn)在這個(gè)功能沒什么用。

編輯高度和編輯顏色的切換
為什么當(dāng)我選擇一個(gè)顏色后自動(dòng)取消選擇高度了?
這個(gè)情況發(fā)生在你把所有的選項(xiàng)都放在一個(gè)選項(xiàng)組時(shí),你可能復(fù)制了一份顏色選項(xiàng)卡然后修改成高度選項(xiàng)卡,但沒有清理它的選項(xiàng)組。


3.2 筆刷尺寸

要實(shí)現(xiàn)一個(gè)可以變化的筆刷尺寸,添加一個(gè)整數(shù)變量brushSize和一個(gè)在UI中設(shè)置它的方法。因?yàn)橐褂没瑒?dòng)條,所以再一次把float參數(shù)轉(zhuǎn)換為整數(shù)。

筆刷尺寸滑動(dòng)條

你可以通過復(fù)制高度的滑動(dòng)條來添加一個(gè)新的滑動(dòng)條,修改它的最大值為4并關(guān)聯(lián)正確的方法,這里還同時(shí)給它添加了一個(gè)標(biāo)簽。

滑動(dòng)條的設(shè)置

現(xiàn)在需要用EditCells方法編輯多個(gè)單元格,它負(fù)責(zé)調(diào)用所有受影響的單元格的EditCell方法,原本選擇的單元格將作為筆刷的中心。

筆刷的尺寸定義了我們的編輯范圍的半徑,當(dāng)半徑為0時(shí),就僅包含中心單元格。當(dāng)半徑為1時(shí),包含中心單元格與其所有相鄰單元格。當(dāng)半徑為2時(shí),還包含相鄰單元格的直接相鄰單元格,以此類推。

半徑為3的尺寸


剩下的部分可以通過從最上面一行循環(huán)到中心行得到,這里除了排除中間行外剩余邏輯是對稱的。

尺寸為2的完整筆刷大小

功能基本是正確的,除了當(dāng)筆刷延伸到地圖邊界之外時(shí)。而當(dāng)其發(fā)生時(shí)會報(bào)一個(gè)數(shù)組越界異常。為了防止這種情況發(fā)生,在HexGrid.GetCell里檢測邊界并且當(dāng)獲取不存在的單元格時(shí)返回null。

為了防止報(bào)空引用異常,HexMapEditor需要在編輯前檢查是否真的存在這個(gè)單元格。

使用多種筆刷尺寸

3.3 單元格標(biāo)簽顯示切換

大多數(shù)情況下可能不需要顯示單元格的標(biāo)簽,所以我們做一個(gè)切換是否顯示的功能。由于每一個(gè)地圖塊的管理器都有它自己的canvas,所以在HexGridChunk中添加一個(gè)ShowUI方法,當(dāng)UI需要顯示時(shí)激活它,否則就關(guān)閉它。

在Awake時(shí)默認(rèn)隱藏標(biāo)簽UI。

由于是切換整張地圖的標(biāo)簽UI顯示,同樣在HexGrid中添加一個(gè)ShowUI方法,它就簡單的把切換請求傳遞到所有地圖塊中。

HexMapEditor也同樣創(chuàng)建調(diào)用這個(gè)方法,把切換請求轉(zhuǎn)發(fā)到HexGrid中。

最后添加一個(gè)toggle到UI上并綁定這個(gè)方法。

標(biāo)簽選項(xiàng)

下一篇教程是:https://catlikecoding.com/unity/tutorials/hex-map/part-6/

本期工程地址:https://github.com/tank1018702/Hex-Map-Learning/tree/Elevation


有想系統(tǒng)學(xué)習(xí)游戲開發(fā)的童鞋,歡迎訪問http://levelpp.com/??

有專業(yè)開發(fā)交(gao)流(ji)群等待大家強(qiáng)勢插入:869551769

HexMap學(xué)習(xí)筆記(五)——更大的地圖的評論 (共 條)

分享到微博請遵守國家法律
赤城县| 平江县| 永平县| 东港市| 布尔津县| 三江| 定日县| 自贡市| 信阳市| 沭阳县| 全椒县| 广宗县| 林甸县| 莫力| 新丰县| 玉环县| 壶关县| 兰西县| 双桥区| 闸北区| 红河县| 拜泉县| 康马县| 皋兰县| 舒城县| 安多县| 阜宁县| 八宿县| 永平县| 乐山市| 通河县| 苍梧县| 南开区| 泸西县| 防城港市| 成安县| 韶关市| 德兴市| 平乐县| 凤冈县| 荔浦县|