[Unity + Bolt] 可拾取物(Pickable Item)的交互制作


創(chuàng)建可拾取物

創(chuàng)建一個(gè)用來被“拾取”的物體。

可拾取物的造型我使用了一個(gè)小球,放在一個(gè)名為“Pickable”的空物體中。交互做在Pickable上,美術(shù)造型可以隨意更換。

刪掉小球的碰撞體,給Pickable添加一個(gè)Sphere Collider,設(shè)置好合適的大小,勾選上Is Trigger選項(xiàng)。這個(gè)Collider就是觸發(fā)器,玩家必須在其范圍內(nèi)才能進(jìn)行“拾取”操作。


UI的制作

然后要制作一個(gè)UI,提示玩家可以進(jìn)行“拾取”操作了。這個(gè)UI需要懸浮在Pickable上面,因此我選擇將其做成場(chǎng)景UI物體而非全局UI覆蓋。

給Pickable添加一個(gè)Canvas作為其子物體,命名為Pickable_Canvas,然后在Pickable_Canvas下添加一個(gè)Panel以方便觀察。

Pickable_Canvas的Render Mode要改成World Space。這樣才是場(chǎng)景UI而非全局UI。

這里將Scale都設(shè)置成0.01是為了方便設(shè)置其長(zhǎng)寬尺寸。由于Rect Transform的長(zhǎng)寬尺度單位是“米”,因此對(duì)于一個(gè)實(shí)際大小10cm左右的Canvas來說,Width和Height都只有0.x甚至0.0x,不方便調(diào)節(jié)。Scale設(shè)置為0.01之后,長(zhǎng)寬尺度單位就變成了“0.01米(厘米)”,這就很方便了。

然后將Panel上移到合適的位置。當(dāng)然其實(shí)也可以直接上移Pickable_Canvas,兩種方式造成的結(jié)果會(huì)略有不同。


UI的交互

現(xiàn)在的UI好像一塊懸在小球頭頂?shù)恼信?,但我們希望得到的是一個(gè)始終正對(duì)攝影機(jī)的“招牌”。

給Pickable添加一個(gè)Flow Machine,使用Macro模式,保存成Pickable。

建議大家養(yǎng)成使用Macro而非Embed模式的習(xí)慣,對(duì)于代碼復(fù)用非常有幫助。

新建一個(gè)Graph變量“Canvas”用來儲(chǔ)存Pickable_Canvas。因?yàn)槭荕acro模式,所以不能直接指定場(chǎng)景對(duì)象,必須通過Graph來“尋找”。

在Enable Event中添加這一段Graph。幾個(gè)units的作用分別是:按名字在子物體中搜索Pickable_Canvas,并將搜索結(jié)果設(shè)置給變量“Canvas”。順便將Pickable_Canvas設(shè)置為不激活,因?yàn)槌跏紶顟B(tài)時(shí)不需要顯示這個(gè)UI。

然后在Update Event中添加這一段Graph。其作用是每幀獲取Main Camera的旋轉(zhuǎn)值,然后設(shè)置給Pickable_Canvas,這樣就保證了Pickable_Canvas會(huì)一直正對(duì)攝像機(jī)。同時(shí)將Pickable_Canvas設(shè)置為激活,確保運(yùn)行場(chǎng)景的時(shí)候能夠看到這個(gè)UI。

點(diǎn)擊Play,可以看到這個(gè)UI被正確地放置在Pickable的上方了。


可拾取物的交互

下面要制作Pickable對(duì)象與Player之間的交互了。

這里有兩種選擇,我們可以讓Pickable去探測(cè)Player,也可以讓Player去探測(cè)Pickable。這里我選擇讓Pickable去探測(cè)Player。

這段Graph是探測(cè)Player是否進(jìn)入了Pickable的Trigger范圍。如果被Trigger的碰撞體的標(biāo)簽為“Player”,則將Graph變量“canBePicked”設(shè)置為true,并將該碰撞體(Player)的Object變量“itemToPick”設(shè)置為本Pickable物體。

這段Graph是探測(cè)Player是否離開了Pickable的Trigger范圍。如果離開Trigger的碰撞體的標(biāo)簽為“Player”,則將Graph變量“canBePicked”設(shè)置為false,并檢查將該碰撞體(Player)的“itemToPick”變量的取值,如果取值為本Pickable物體,則將“itemToPick”變量的取值設(shè)置為“空(Null)”。

這里有幾點(diǎn)要注意:

  1. 我使用變量“canBePicked”來記錄Pickable的狀態(tài),而不是在這兩個(gè)Graph中直接去做UI Canvas的顯示/消失交互,是為了避免一個(gè)交互邏輯(或者說Graph)太過于復(fù)雜。把一個(gè)復(fù)雜的交互邏輯“拆”成多個(gè)相對(duì)簡(jiǎn)單的邏輯,不僅可以增強(qiáng)可讀性,還可以提高靈活性。
  2. 由于是用Pickable探測(cè)Player,因此需要“告知”Player知道究竟當(dāng)前可拾取的游戲物體是哪一個(gè)。變量“itemToPick”就是用來儲(chǔ)存當(dāng)前可拾取物體的。當(dāng)Player進(jìn)入Trigger范圍時(shí)設(shè)置“itemToPick”,當(dāng)Player離開Trigger范圍時(shí)取消“itemToPick”的設(shè)置。
  3. 有可能Player同時(shí)進(jìn)入多個(gè)Pickable物體的Trigger范圍,但只有最后一個(gè)被Trigger的Pickable會(huì)被記錄在“itemToPick”變量里。因此,在Player離開某個(gè)Pickable的Trigger范圍時(shí),還需要確認(rèn)當(dāng)前記錄在“itemToPick”變量里的Pickable是否就是“自己”,如果不是“自己”就不要管閑事了。

現(xiàn)在有了變量“canBePicked”,就可以用它來切換UI是否顯示了。

修改一下剛才在Update Event中制作的Graph,添加了一個(gè)Branch判斷是否可被拾取,是就顯示UI Canvas,不是就不顯示。

大家可以自己思考一下,如果將這個(gè)邏輯做進(jìn)On Trigger Enter/Exit Event中究竟合不合適。

這段Graph是用來實(shí)現(xiàn)Pickable“被拾取”(其實(shí)就是從場(chǎng)景中被刪除)效果的。這里我用了一個(gè)Custom Event,因?yàn)檫@個(gè)事件需要由玩家的“拾取”動(dòng)作所觸發(fā)。我還添加了一個(gè)Branch,用來判斷這個(gè)Pickable是否可被拾取,防止誤觸發(fā)。

Custom Event是Bolt非常非常重要的功能。Bolt目前沒有“函數(shù)(function)”的概念,Custom Event可以勉強(qiáng)當(dāng)做半個(gè)函數(shù)來用,缺陷是沒有輸出值。

Player上的相關(guān)交互邏輯是這樣的:

  • 首先讓Player面向(Look At)待拾取物
  • 然后讓Player播放Pickup動(dòng)畫(通過Animator來實(shí)現(xiàn))
  • 等待0.6秒(大概就是Pickup動(dòng)畫播放到“拾起”那一刻的時(shí)間),觸發(fā)待拾取物的“被拾取”Custom Event
  • 由于使用了Wait,需要勾選On Enter State Event的Coroutine選項(xiàng)(否則運(yùn)行時(shí)會(huì)報(bào)錯(cuò))

注意:這個(gè)Player我是用State Machine(狀態(tài)機(jī))在做,所以是On Enter State Event開頭。關(guān)于State Machine的內(nèi)容不在本文范圍以內(nèi),大家理解邏輯就好。


最后的效果是這樣的:


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容