來(lái)源:映維網(wǎng)
在今年8月,映維網(wǎng)分享了Fanbank首席技術(shù)官斯科特·蓋耶(Scott Geye)是如何用Quest和Unity等工具制作一個(gè)炫酷的混合現(xiàn)實(shí)公寓?,F(xiàn)在,蓋耶又通過(guò)后續(xù)博文介紹了在所述基礎(chǔ)上進(jìn)一步優(yōu)化混合現(xiàn)實(shí)公寓的一系列方式。
延伸閱讀:如何用Oculus Quest將自己公寓打造成MR科幻游樂(lè)場(chǎng)
下面是映維網(wǎng)的具體整理:
如何用按鈕來(lái)為你的公寓實(shí)現(xiàn)交互性
在上一篇教程中,我介紹了如何用Oculus Quest和Unity打造一個(gè)混合現(xiàn)實(shí)公寓的所有步驟。在這個(gè)基礎(chǔ)之上,我們可以進(jìn)一步探索強(qiáng)化虛擬公寓的有趣方式。
在我成長(zhǎng)的過(guò)程中,我喜歡諸如《Cosmic Osmo》和《神秘島》這樣的游戲(以及最近的《The Room》)。所述游戲要求你探索一個(gè)虛擬世界,并通過(guò)與環(huán)境交互來(lái)發(fā)現(xiàn)隱藏的線索。當(dāng)我在思考如何通過(guò)各種有趣功能來(lái)進(jìn)一步裝飾我的公寓時(shí),先行隱藏相關(guān)控件,并在執(zhí)行特定操作時(shí)顯露成為了自然而然的下一步。我想看看自己是否能重現(xiàn)當(dāng)在房間里發(fā)現(xiàn)不存在于現(xiàn)實(shí)世界中的元素時(shí)的興奮感覺(jué)。
我決定把我的咖啡桌作為主控制中心,但在收到請(qǐng)求之前,我會(huì)先把實(shí)際的控件隱藏在桌子里面。一旦控件顯露,這將提供允許我與整個(gè)房間進(jìn)行交互的方式。我想看看在屋頂開(kāi)一個(gè)大洞會(huì)是什么樣子,因?yàn)檫@樣我就想能夠動(dòng)態(tài)地調(diào)整公寓內(nèi)外的環(huán)境。我同時(shí)想看看擺設(shè)一臺(tái)大電視的感覺(jué)。200寸的屏幕可能有點(diǎn)夸張,但超級(jí)酷。
在下面這個(gè)教程中,我將向你介紹我為房間增加交互性的技術(shù)。希望本文能夠?yàn)槟闾峁﹩l(fā)鼓勵(lì),并幫助你天馬行空地打造屬于自己的科幻未來(lái)公寓。
在開(kāi)始之前,我們需要一定的代碼操作,但我編寫(xiě)的腳本可以直接放到你的項(xiàng)目中。當(dāng)然,如果你希望進(jìn)一步擴(kuò)展,我的代碼編輯起來(lái)應(yīng)該足夠簡(jiǎn)單。
1. 制作一個(gè)隱藏的隔間
在打造和裝飾我的數(shù)字公寓之后,一個(gè)主要的挑戰(zhàn)是如何創(chuàng)造一個(gè)藏匿控件的地方。我最初并沒(méi)有設(shè)計(jì)任何包含隔間或活板門(mén)的元素,我所有的家具都來(lái)自于預(yù)先建造的asset。最簡(jiǎn)單的方法是使用ProBuilder并在任何需要的地方打一個(gè)洞。
ProBuilder有一個(gè)實(shí)驗(yàn)性的Boolean工具,它允許你將兩個(gè)ProBuilder對(duì)象合并,或從另一個(gè)對(duì)象中減去一個(gè)的體積。根據(jù)我的經(jīng)驗(yàn),這個(gè)工具完全符合我的預(yù)期,所以不要被實(shí)驗(yàn)這個(gè)詞嚇倒。如果嘗試使用更復(fù)雜的形狀,你肯定會(huì)遇到一些小麻煩。所述工具必須從一組三角形中重新創(chuàng)建每個(gè)面,所以對(duì)于原本可能是每邊有兩個(gè)三角形的立方體,如果你減去圓形,情況就會(huì)變得非常復(fù)雜,會(huì)出現(xiàn)大量的新三角形。這確實(shí)有可能導(dǎo)致渲染問(wèn)題,但這個(gè)工具應(yīng)該不會(huì)破壞原始對(duì)象,所以你可以嘗試一下,看看它的處理效果如何。
你需要在ProBuilder下的Unity Preferences中打開(kāi)實(shí)驗(yàn)功能,然后從ProBuilder/Experimental/Boolean(CSG)Tool下的Tools菜單打開(kāi)Boolean Tool。
我首先是在咖啡桌上開(kāi)一個(gè)洞并用來(lái)放置控制面板。我為桌子使用的預(yù)制件被分割成用于桌面和桌腿的對(duì)象,但如果你需要,你應(yīng)該非常容易從零開(kāi)始創(chuàng)建一個(gè)類似的桌子。
要使用Boolean Tool,兩個(gè)對(duì)象都必須是ProBuilder對(duì)象,所以你可以使用ProBuilder創(chuàng)建一個(gè)新的多維數(shù)據(jù)集,并使其與原始桌面大小相同,然后關(guān)閉原始桌面。接下來(lái),創(chuàng)建一個(gè)ProBuilder立方體,將其用作從新桌面(即孔)減去的體積。將它們正確地放在彼此上方,打開(kāi)Boolean Tool,將新的桌面從對(duì)象Hierarchy拖到第一個(gè)槽中,然后將減法立方體拖到第二個(gè)槽中。將你的Operation選為Subtraction并點(diǎn)擊Apply。
這樣你就留下三個(gè)對(duì)象:原始的兩個(gè)對(duì)象和一個(gè)新對(duì)象,后者是減法運(yùn)算的結(jié)果。這三者在制作動(dòng)畫(huà)時(shí)非常有用,所以要相應(yīng)地重命名它們,暫時(shí)隱藏兩個(gè)原始對(duì)象,這樣你就可以看到減法的效果了。
2. 設(shè)置桌子
現(xiàn)在我們的桌子有了一個(gè)用于隱藏隔間的洞,而我們同時(shí)需要?jiǎng)?chuàng)建隔間的內(nèi)部、控制面板本身、以及用于顯露面板的門(mén)。我們將使用Unity的動(dòng)畫(huà)工具來(lái)確保所有一切協(xié)調(diào)地移動(dòng)。
要?jiǎng)?chuàng)建隱藏分區(qū)的內(nèi)部,請(qǐng)找到用于執(zhí)行布爾減法的立方體。選擇頂面,然后稍微插入表面,形成我們隔間的邊緣。
接下來(lái),朝立方體底部向下擠出插入面。你應(yīng)該留下一個(gè)看起來(lái)像空盒子的元素。把你的立方體放在桌面的洞里,使立方體的頂部略低于桌面。
下一步,創(chuàng)建一個(gè)新的立方體來(lái)作為我們的控制面板,將其移動(dòng)到隱藏的隔間內(nèi)并調(diào)整大小。
然后,創(chuàng)建另一個(gè)立方體用作可伸縮門(mén)。把它移到適當(dāng)?shù)牡胤?,確保它的大小能蓋住這個(gè)洞,并且與桌面齊平。確定寬度的測(cè)量值,除以這個(gè)數(shù)的一半,然后以這個(gè)寬度設(shè)置立方體。接下來(lái),復(fù)制立方體,這樣你就有了兩個(gè)門(mén)。相應(yīng)地定位第二個(gè)門(mén)。
3. 設(shè)置控制面板的動(dòng)畫(huà)
為了一次過(guò)設(shè)置所有桌面對(duì)象的動(dòng)畫(huà),我們需要將它們?nèi)恳苿?dòng)到Hierarchy的同一父對(duì)象下面。轉(zhuǎn)到Game Object菜單,選擇Create Empty,將其重命名為Control Panel,然后將所有桌面對(duì)象拖動(dòng)到所述對(duì)象之下。
為了簡(jiǎn)單起見(jiàn),我們將使用Unity的內(nèi)置動(dòng)畫(huà)工具。通過(guò)選擇Window/Animation/Animation菜單來(lái)打開(kāi)Animation視圖。選擇我們的Control Panel父對(duì)象,然后在Animation視圖中單擊Create以創(chuàng)建一個(gè)新的動(dòng)畫(huà)片段,并將其命名為ControlPanelAnim。
在視圖中打開(kāi)新片段后,單擊紅色錄制圖標(biāo)并將時(shí)間軸移到1:00(1秒)標(biāo)記位置。現(xiàn)在,選擇每一個(gè)伸縮門(mén),將它們縮小到零單位寬,并將它們與孔的最近邊對(duì)齊。關(guān)閉錄制并點(diǎn)擊播放。門(mén)應(yīng)該從中間打開(kāi)并顯露你的面板。
返回到1:00標(biāo)記,然后單擊Animation視圖中的Add Property按鈕。打開(kāi)Panel/Transform并單擊Rotation旁邊的加號(hào)(+)按鈕。通過(guò)同樣的過(guò)程來(lái)添加Position。然后單擊動(dòng)畫(huà)控件第二行的Add Keyframe按鈕。這將鎖定面板的旋轉(zhuǎn)和位置,直到所述時(shí)間點(diǎn),這樣它就不會(huì)從0:00移動(dòng)到1:00。接下來(lái),將時(shí)間軸移到2:00,單擊錄制并將面板旋轉(zhuǎn)45度,然后調(diào)整其位置,使其面向與房間中面板交互的任何位置。再次關(guān)閉錄制并點(diǎn)擊播放,從而確保你的面板被伸縮門(mén)正確顯示并旋轉(zhuǎn)到位。
如果運(yùn)行整個(gè)場(chǎng)景,你會(huì)注意到動(dòng)畫(huà)立即播放。因?yàn)槲覀兿M麆?dòng)畫(huà)被觸發(fā),所以我們需要在Animator窗口中進(jìn)行一定調(diào)整。選擇ControlPanel對(duì)象并打開(kāi)Animator窗口。你將看到一個(gè)連接到ControlPanelAnim狀態(tài)的Entry狀態(tài)。右鍵單擊它并創(chuàng)建一個(gè)新的Empty狀態(tài),然后將其命名為IdleStart。右鍵單擊Entry狀態(tài)并選擇setstatemachine Default State,然后將轉(zhuǎn)換線拖到IdleStart狀態(tài)?,F(xiàn)在,當(dāng)你開(kāi)始場(chǎng)景時(shí),動(dòng)畫(huà)在被觸發(fā)之前講不會(huì)播放,因?yàn)樗肋h(yuǎn)不會(huì)轉(zhuǎn)換到ControlPanelAnim狀態(tài)。
4. 按鈕
我想通過(guò)一個(gè)簡(jiǎn)單的按鈕機(jī)制來(lái)觸發(fā)房間里的所有動(dòng)畫(huà)。如果你想深入U(xiǎn)I,Mixed Reality Tool Kit(MRTK)是一個(gè)很好的資源。但這一次我們將使用Oculus Sample Framework中的預(yù)置和腳本。
如果沒(méi)有試過(guò),我建議你嘗試一下Model Train Hand Tracking場(chǎng)景(Assets/Oculus/SampleFramework/Usage/handsinteractiontrainsect)。
這實(shí)際上相當(dāng)有趣。
要在場(chǎng)景中使用相同的按鈕,需要添加以下三個(gè)預(yù)制件:
Assets/Oculus/SampleFramework/Core/HandsInteraction/Prefabs/InteractableToolsSDKDriverAssets/Oculus/SampleFramework/Core/HandsInteraction/Prefabs/HandsManagerAssets/Oculus/SampleFramework/Usage/HandsTrainExample/Prefabs/NearFieldButton.prefab
把NearFieldButton放在場(chǎng)景中的合適地方(我選擇了桌子的邊緣)。下一步,我們需要配置所有一切以適配場(chǎng)景。
單擊HandsManager對(duì)象并在Inspector中查看HandManger腳本。返回到Hierarchy,打開(kāi)OVRCameraRig對(duì)象,直到你發(fā)現(xiàn)Right和LeftHandAnchors。將每只手對(duì)應(yīng)的OvrHandPrefabs拖到HandsManger Inspector中相應(yīng)的字段中。
另外,對(duì)于每個(gè)OvrHandPrefab,你需要確保在Inspector中啟用了Enable Physics Capsules。這將在每個(gè)食指的尖端添加一個(gè)球體,并允許系統(tǒng)捕捉與手指和按鈕的交互。
現(xiàn)在我們已經(jīng)設(shè)置了按鈕交互,下面我們來(lái)構(gòu)建和運(yùn)行項(xiàng)目,從而確保手部追蹤工作正常。當(dāng)你觸碰按鈕時(shí),它應(yīng)該會(huì)亮起,而你會(huì)聽(tīng)到一聲咔嗒聲。
5. 觸發(fā)動(dòng)畫(huà)
現(xiàn)在我們已經(jīng)完成了按鈕和動(dòng)畫(huà),下面我們將兩者結(jié)合起來(lái)。這是我們的第一個(gè)腳本。首先,我們需要?jiǎng)?chuàng)建一個(gè)空對(duì)象來(lái)應(yīng)用腳本。創(chuàng)建一個(gè)新的空對(duì)象并將其稱為PanelController。接下來(lái),為PanelController打開(kāi)Inspector,單擊addcomponent,然后單擊NewScript并調(diào)用文件PanelController。下面是我們用于觸發(fā)第一個(gè)動(dòng)畫(huà)的初始代碼:
你應(yīng)該能夠在任何文本編輯器中打開(kāi)腳本,復(fù)制/粘貼上面的內(nèi)容,保存文件并將其自動(dòng)導(dǎo)入U(xiǎn)nity。如果你再次為Panel Controller對(duì)象查看Inspector,你將在Panel Controller(Script)部分看到一個(gè)空的Panel字段。將ControlPanel父對(duì)象拖動(dòng)到所述字段,以便我們?cè)谀_本中使用它。
我已經(jīng)將腳本設(shè)置成你可以直接在編輯器中運(yùn)行項(xiàng)目,并通過(guò)在Game窗口中點(diǎn)擊P鍵來(lái)測(cè)試動(dòng)畫(huà)。當(dāng)場(chǎng)景運(yùn)行時(shí),動(dòng)畫(huà)應(yīng)該會(huì)不斷循環(huán)。要關(guān)閉循環(huán),請(qǐng)停止項(xiàng)目,在資源中找到ControlPanelAnim文件,單擊文件并查看Inspector,然后取消選中Loop Time。
現(xiàn)在,如果嘗試重新運(yùn)行并按P鍵,動(dòng)畫(huà)將只運(yùn)行一次。
要將動(dòng)畫(huà)鏈接到按鈕,我們需要告訴按鈕從腳本調(diào)用RunControlPanelAnimation函數(shù)。單擊NearFieldButton并導(dǎo)航到ButtonController(Script)。單擊InteractionableStateChanged列表下的加號(hào)(+)按鈕,并將PanelController對(duì)象拖動(dòng)到None(object)字段?,F(xiàn)在你可以選擇PanelController/RunControlPanelAnimation。
現(xiàn)在,你可以在頭顯中構(gòu)建并運(yùn)行項(xiàng)目。單擊按鈕后你會(huì)看到動(dòng)畫(huà)開(kāi)始。
6. 重新隱藏面板
面板打開(kāi)后,我希望能夠再次單擊按鈕以關(guān)閉面板,甚至可以單擊動(dòng)畫(huà)中間的按鈕來(lái)再次關(guān)閉/打開(kāi)面板(加分項(xiàng))。我們不需要?jiǎng)?chuàng)建單獨(dú)的動(dòng)畫(huà)來(lái)隱藏面板,我們只需反向運(yùn)行相同的動(dòng)畫(huà),并使用Animator窗口、Animation States和腳本更新。
我們的計(jì)劃是將一個(gè)動(dòng)畫(huà)狀態(tài)用于打開(kāi)面板,一個(gè)用于關(guān)閉面板,一個(gè)狀態(tài)用于動(dòng)畫(huà)開(kāi)始前的待機(jī)時(shí)間,另一個(gè)用于動(dòng)畫(huà)結(jié)束后的待機(jī)時(shí)間。這樣,我們就可以從腳本中測(cè)試動(dòng)Animaor的狀態(tài),并進(jìn)行適當(dāng)?shù)霓D(zhuǎn)換。
在Animator窗口中,單擊ControlPanelAnim狀態(tài)并將其重命名為AnimForward。復(fù)制(復(fù)制/粘貼)狀態(tài)并將其命名為AnimBackward。選擇AnimBackward并在Inspector中將Speed值更改為-1,這樣動(dòng)畫(huà)在所述狀態(tài)下將向后運(yùn)行。
選擇IdleStart狀態(tài),將Speed設(shè)置為零,然后將ControlPanelAnim從Assets拖動(dòng)到空的Motion字段中。復(fù)制IdleStart狀態(tài)并將復(fù)制重命名為IdleEnd。添加動(dòng)畫(huà)以確保片段的第一幀和最后一幀將在所述狀態(tài)下播放。
下一步,通過(guò)右鍵單擊每個(gè)狀態(tài)并選擇Make Transtion來(lái)創(chuàng)建三個(gè)新的變換:
IdleState to AnimForwardAnimBackward to IdleStateAnimForward to IdleEnd
現(xiàn)在,單擊AnimForward to IdleEnd轉(zhuǎn)換,打開(kāi)Inspector中的Settings并將Transition Offset設(shè)置為1。當(dāng)處于IndleEnd狀態(tài)時(shí),這將強(qiáng)制動(dòng)畫(huà)在最后一幀待機(jī)。
所有這一切的結(jié)果是,如果AnimForward播放到最后,IdleEnd將開(kāi)始并停留在最后一幀。如果AnimBackward播放到最后,IdleStart將開(kāi)始并停留在第一幀。
最后,我們只需要更新腳本來(lái)處理這些新?tīng)顟B(tài)。
我所做的只是更新我們的processAnimation函數(shù),從而處理我們可能發(fā)現(xiàn)的所有四種狀態(tài):
IdleState:向前播放動(dòng)畫(huà)IdleEnd:向后播放動(dòng)畫(huà)AnimForward:我們正在向前播放動(dòng)畫(huà),所以我們需要切換到在動(dòng)畫(huà)時(shí)間軸的同一位置向后播放動(dòng)畫(huà)。AnimBackward:與Animforward相同,但我們是在向后播放,所以我們需要切換到向前播放動(dòng)畫(huà)。
我們只能檢索每個(gè)正在播放的狀態(tài)的時(shí)間。這是一個(gè)介于0和1之間的值,它表示我們?cè)趧?dòng)畫(huà)中的距離,不考慮片段的長(zhǎng)度(例如百分比)。當(dāng)在狀態(tài)之間切換時(shí),我們需要同時(shí)播放反向片段,但要從時(shí)間軸的另一端開(kāi)始播放。這需要我們計(jì)算當(dāng)前播放片段的標(biāo)準(zhǔn)化時(shí)間的倒數(shù),并將值作為新的開(kāi)始位置,然后傳遞給另一個(gè)狀態(tài)的播放函數(shù)。
有了腳本設(shè)置,我們可以在動(dòng)畫(huà)的任何階段點(diǎn)擊按鈕以令它前進(jìn)或后退,并在開(kāi)始和結(jié)束時(shí)暫停。
7. 改變環(huán)境
現(xiàn)在我們有了控制面板,我們只需為控制面板添加額外的近場(chǎng)按鈕,并在腳本中添加一定的附加功能,然后就可以為我們的房間添加額外的功能。
首先,我們來(lái)改變墻壁的顏色。在場(chǎng)景中,將另一個(gè)NearFieldButton放置在面板對(duì)象的上方,然后使其成為面板的子對(duì)象,以便當(dāng)面板移動(dòng)時(shí),按鈕同樣會(huì)隨之移動(dòng)。
接下來(lái)我們更新腳本以設(shè)置墻壁的顏色。
有兩個(gè)新的公共變量將在PanelController對(duì)象的Inspector中顯示為空字段。在Wall字段中,選擇當(dāng)前用于墻壁的材質(zhì)。如果對(duì)不想修改的其他對(duì)象使用相同的材質(zhì),則應(yīng)復(fù)制墻壁材質(zhì)并僅將其應(yīng)用于墻壁。第二個(gè)字段是一個(gè)名為Color1的簡(jiǎn)單顏色選擇器。只需選擇你喜歡的顏色即可。
回到腳本,我們有一個(gè)名為SetColor的簡(jiǎn)單函數(shù),它將對(duì)墻壁材質(zhì)應(yīng)用顏色。點(diǎn)擊1并從SetWallColor1函數(shù)啟動(dòng)顏色更改。
最后一步是選擇新的NearFieldButton,然后再次配置函數(shù)調(diào)用,方法是單擊InteractiveStateChanged列表下的加號(hào)(+)按鈕,將PanelController對(duì)象拖動(dòng)到顯示None(object)的打開(kāi)字段中,然后選擇PanelController/RunSetWallColor1。
我已經(jīng)將腳本設(shè)置成你可以根據(jù)需要多次復(fù)制/粘貼顏色變量和函數(shù),以便為不同顏色設(shè)置多個(gè)按鈕。你同時(shí)可以使用類似的設(shè)置來(lái)調(diào)整skybox。方法是創(chuàng)建skybox材質(zhì)的公共變量,并在按鈕觸發(fā)所選腳本函數(shù)時(shí)使用一個(gè)簡(jiǎn)單的函數(shù)來(lái)設(shè)置它們。
當(dāng)開(kāi)始添加多個(gè)按鈕時(shí),你可能需要在面板添加文本標(biāo)記。我使用了TextMeshPro,它比Unity的內(nèi)置UI文本要好得多。你只需通過(guò)Unity Registry將其安裝到Package Manager即可。
最終的房間控制裝置
8. 劇院模式和伸縮屋頂
現(xiàn)在所有一切已經(jīng)準(zhǔn)備妥當(dāng),你能夠觸發(fā)任何動(dòng)畫(huà)或更改場(chǎng)景中任何對(duì)象的屬性。要制作一個(gè)可伸縮屋頂,我最終采用了與控制面板相同的步驟。訣竅是選擇代表屋頂?shù)姆块g對(duì)象的面,然后將其分離以創(chuàng)建一個(gè)單獨(dú)的對(duì)象,這樣我就可以使用Boolean Tool并在其中創(chuàng)建一個(gè)大洞。
創(chuàng)建劇院模式涉及一個(gè)更為復(fù)雜的動(dòng)畫(huà),但就像其他動(dòng)畫(huà)一樣,我通過(guò)設(shè)置時(shí)間軸和一次記錄一個(gè)對(duì)象的運(yùn)動(dòng)來(lái)建立動(dòng)畫(huà)。我同時(shí)降低了房間里所有照明的亮度,使實(shí)際的電視屏幕縮放到適合房間的大小。
這里提供了我所有動(dòng)畫(huà)和交互的最終腳本。
9. 下一步
我到了一個(gè)不得不停下來(lái)的時(shí)候。對(duì)于這個(gè)房間,我想做的事情沒(méi)有盡頭。在本教程中,我們確實(shí)將自己限制為僅觸發(fā)動(dòng)畫(huà)或?qū)傩愿?。多虧了Unity動(dòng)畫(huà)工具中內(nèi)置的功能,我們可以走得很遠(yuǎn)。
對(duì)于我的下一個(gè)項(xiàng)目,我想嘗試類似于在我們混合現(xiàn)實(shí)平臺(tái)中的新應(yīng)用程序。這需要我們以新的方式使用物理對(duì)象。
原文鏈接:https://yivian.com/news/78527.html
轉(zhuǎn)載須知:轉(zhuǎn)載摘編需注明來(lái)源映維網(wǎng)并保留本文鏈接