詳解新版Unity中可嵌套的Prefab系統(tǒng)

前言

Prefab,也就是大家熟知的預(yù)制件(本文中,我們依然使用它的英文名字——Prefab),它是Unity中一個(gè)極其重要的概念。Prefab用來保存GameObjects(以及其所有的子GameObejct)、組件以及屬性。在實(shí)例化Prefab的時(shí)候,Prefab扮演著資源模版的角色。
Unity2018.3的Beta版本中支持了可嵌套的Prefab系統(tǒng),這個(gè)新特性使得能夠把一個(gè)大型的建筑剝離成粒度更小的Prefab來。例如大型建筑,可以嵌套房間的Prefab,以此類推,房間的Prefab也可以嵌套更小的家具的Prefab。Prefab嵌套的靈活性極大的增強(qiáng)了Pefab在多人協(xié)同開發(fā)的效率,同時(shí)新版的Prefab系統(tǒng)在Prefab的編輯上也有很大的改變,使用起來非常方便。
接下來,我們就來一覽新版的Prefab系統(tǒng)吧。開始正文之前,show一張我們工作室的游戲截圖

上圖為迷霧偵探,手領(lǐng)出品

一、創(chuàng)建Prefab

創(chuàng)建Prefab資源

創(chuàng)建Prefab同之前版本的Unity引擎一樣,我們只需要把Hierarchy視圖中GameObject拖到Project視圖里,穿著藍(lán)色衣服的Prefab資源就出現(xiàn)在Project的視圖中了。

Project視圖中的Prefab資源
二、Prefab實(shí)例化

創(chuàng)建Prefab實(shí)例的方法也沒有改變,還是下面兩個(gè)途徑:

  • 從Project視圖中直接把Prefab拖動(dòng)到Scene或者Hierarchy視圖里面。
  • 在運(yùn)行時(shí)通過Instantiate這個(gè)API來創(chuàng)建Prefab的實(shí)例。
在Prefab模式下編輯Prefab

Prefab模式,是一種專門用來支持單獨(dú)編輯Prefab的一種模式。Prefab模式允許在一個(gè)獨(dú)立的場(chǎng)景里面查看和編輯Prefab里面的內(nèi)容。

進(jìn)入Prefab模式

這里有兩種方法可以進(jìn)入Prefab模式:

  • 在Project視圖中雙擊Prefab
  • 在Hierarchy視圖中點(diǎn)擊Prefab實(shí)例的箭頭按鈕

注意:在Prefab模式下,Prefab的根節(jié)點(diǎn)是普通類型的GameObject(并是不顯示成Prefab實(shí)例特有的藍(lán)色圖標(biāo))

在Prefab模式下的Scene和Hierarchy視圖.

在Prefab模式下,Scene視圖的上方會(huì)顯示一個(gè)導(dǎo)航欄。使用導(dǎo)航按鈕可以在主場(chǎng)景或其他Prefab之間切換。此外,在Hierarchy視圖頂部,也會(huì)顯示一個(gè)標(biāo)題欄,上面顯示當(dāng)前打開的Prefab的名字。點(diǎn)擊標(biāo)題欄中的左箭頭按鈕,也可以用于回到主場(chǎng)景。

自動(dòng)保存

在Prefab下,如果點(diǎn)選了自動(dòng)保存的話,任何對(duì)Prefab的改動(dòng),都將會(huì)自動(dòng)的保存到Prefab資源中去(自動(dòng)保存默認(rèn)是開啟的)。

自動(dòng)保存的開關(guān)按鈕位于場(chǎng)景視圖的右上角(在Prefab模式下)

我們也可以關(guān)閉自動(dòng)保存。在關(guān)閉之后,當(dāng)我們退出當(dāng)前Prefab的Prefab模式的時(shí)候,編輯器會(huì)提醒我們是否保存修改。在某些情況下,關(guān)閉自動(dòng)保存是非常有用的。

設(shè)置Prefab模式的編輯環(huán)境

Prefab模式下,默認(rèn)會(huì)顯示一個(gè)空?qǐng)鼍?。我們可以指定一個(gè)特定的場(chǎng)景來作為Prefab模式的背景場(chǎng)景。(背景場(chǎng)景中的對(duì)象,都會(huì)顯示在Prefab模式中,但是這些對(duì)象是無法被選中的,也不會(huì)顯示在Hierarcy視圖中。)
我們可以通過Editor Settings來設(shè)置這個(gè)背景場(chǎng)景。在打開主菜單“Edit->Project Settings -> Editor”,找到“Prefab Editing Environments”。其中“Regular Environment”適用于大多數(shù)的Prefab,“UI Environment”適用于大多數(shù)的UI相關(guān)的Prefab。

在編輯器的Project Settings中設(shè)置Prefab的編輯環(huán)境
三、實(shí)例的覆蓋值

所謂覆蓋值,簡(jiǎn)單地說,修改了實(shí)例的值就會(huì)產(chǎn)生覆蓋效果,Prefab實(shí)例中值覆蓋了Prefab資源中的值,這就是覆蓋值的定義。
這個(gè)特性是非常有用的,例如,當(dāng)你需要?jiǎng)?chuàng)建多個(gè)相似的NPC,但是又需要有一些少許的差異(也就是說實(shí)例和Prefab不會(huì)完全一致的時(shí)候)。
我們對(duì)Prefab實(shí)例中的值進(jìn)行修改,就相當(dāng)于創(chuàng)建了一個(gè)覆蓋值。 修改的動(dòng)作,我們可以理解為覆蓋。

新版的Prefab支持下面幾種類型的覆蓋

  • 修改組件中屬性的值
  • 添加/刪除組件
  • 添加一個(gè)子的GameObject

同時(shí)這里也有一些限制:不能修改該P(yáng)refab中的Gameobject的根節(jié)點(diǎn),也不能刪除屬于Prefab的GameObject(可以通過active為false的方法來繞過)

為了直觀地看到被覆蓋的屬性,Unity把Inspector中被覆蓋的屬性的名字用粗體字顯示,同時(shí)在左邊的邊緣顯示了一條藍(lán)色的線。如果是添加的一個(gè)全新的Componet的話,藍(lán)色的線會(huì)跨過整個(gè)Componet。

Prefab 實(shí)例覆蓋了"Dynamic Occluded"屬性。同時(shí)新增加了一個(gè)Rigidbody

添加或者移除組件,會(huì)在Inspector界面的名字旁邊生成+或者-的標(biāo)記。如果是增加一個(gè)GameObject話,則會(huì)在Hierarchy視圖中的圖標(biāo)旁邊增加+的標(biāo)記。

Prefab實(shí)例中添加了名為Extension的GameObject作為覆蓋
實(shí)例覆蓋值的優(yōu)先級(jí)更高

Prefab實(shí)例的覆蓋值,會(huì)取代來自Prefab資源中的值。換而言之,如果你修改了Prefab資源中的一個(gè)值,這個(gè)值對(duì)于被覆蓋了值的實(shí)例來說,是不會(huì)生效的。<u>因此,發(fā)現(xiàn)修改了Prefab中的值,但不是所有的Prefab實(shí)例都有效果,那么建議檢查一下這個(gè)值是否是在沒生效的Prefab實(shí)例中被覆蓋了。</u>
最后,為了盡量去避免潛在的問題和困惑,建議只在必要的情況下使用實(shí)例覆蓋值取代Prefab的值。

四、通過實(shí)例來編輯Prefab

當(dāng)選中Prefab實(shí)例的根節(jié)點(diǎn)時(shí)候,Inspector界面中會(huì)出現(xiàn)3個(gè)按鈕,分別是Open、Select和Overrides。
點(diǎn)擊Open按鈕,將直接進(jìn)入Prefab模式,點(diǎn)擊Select,將會(huì)在Proejct視圖中選中Prefab資源。點(diǎn)擊Overrides,則會(huì)彈出一個(gè)下拉窗口。重點(diǎn)說下Overrides.

Overrides下拉窗口

Overrides下拉窗口中可以查看所有修改過的數(shù)據(jù)項(xiàng)(例如屬性,組件,添加的GameObjects等)。在這個(gè)窗口中,我們可以放棄和應(yīng)用所有的修改。(需要注意的是,如果這個(gè)Prefab是嵌套在其他Prefab中的話,那么Inspector中沒有Overrides按鈕,因此不能打開Overrides窗口)

Overrides下拉列表

通過點(diǎn)擊下拉界面中列表的數(shù)據(jù)項(xiàng),會(huì)彈出一個(gè)懸浮界面。如果是修改的屬性,這個(gè)懸浮界面分為兩個(gè)部分,左邊是來自Prefab資源中的值,右邊是Prefab實(shí)例的值,其中修改過的字段的名字被加粗顯示,同時(shí)在左邊緣有一個(gè)藍(lán)色的豎線。

懸浮對(duì)比框
上下文菜單

另外,所有類型的覆蓋值,都可以通過相關(guān)上下文菜單來進(jìn)行應(yīng)用/撤銷。

在Inspector界面中,加粗顯示覆蓋了Prefab的值的屬性名。右鍵點(diǎn)擊,在彈出的上下文菜單里面,選擇Apply to Prefab或Revert。

Inspector中的上下文菜單

對(duì)于修改過的組件(新增加的組件,組件圖標(biāo)旁邊有一個(gè)+標(biāo)記),可以通過點(diǎn)擊該組件右上角的齒輪按鈕,或者右鍵點(diǎn)擊組件頂部彈出上下文菜單來進(jìn)行操作。



已經(jīng)移除的組件上,會(huì)有一個(gè)-標(biāo)記重疊在組件的圖標(biāo)上。刪除操作也可以通過是上下文菜單來進(jìn)行回滾或應(yīng)用到Prefab資源上。撤銷刪除的組件,這個(gè)組件會(huì)從新回到GameObjct中。應(yīng)用修改的話,會(huì)把這個(gè)組件也從Prefab中也刪除。

image.png

在Prefab實(shí)例中新增加的GameObject的圖標(biāo)上會(huì)疊加一個(gè)+的標(biāo)記。在Hierarchy視圖中,右鍵點(diǎn)擊新增的GameObejct,在彈出的上下文菜單中可以進(jìn)行應(yīng)用和撤銷的操作。

五、Prefab的嵌套

當(dāng)當(dāng)(念一聲和二聲),到了本文最核心的部分了,Prefab的嵌套。Prefab嵌套是指在一個(gè)Prefab中,可以包含其他的Prefab,也就是說,一個(gè)Prefab可以包含在另外一個(gè)Prefab中。做關(guān)卡設(shè)計(jì)的同學(xué),對(duì)以前的Prefab有多難用,有深刻的感受,現(xiàn)在終于可以長(zhǎng)長(zhǎng)地舒口氣了。

在Prefab模式中添加嵌套的Prefab

添加一個(gè)嵌套的Prefab和在場(chǎng)景中添加實(shí)例化Prefab的操作是一樣的,通過把Prefab資源拖動(dòng)到Hierarchy視圖或者Scene視圖中就可以把一個(gè)Prefab實(shí)例添加到已經(jīng)打開的Prefab中去。
這里可以看到,在Prefab模式下打開的Prefab的GameObejct的圖標(biāo),顯示成的是普通的圖標(biāo),而嵌套的Prefab的實(shí)例則顯示著象征了Prefab實(shí)例的藍(lán)色圖標(biāo)。同時(shí)。我們可以像在普通場(chǎng)景中一樣地覆蓋這些Prefab實(shí)例的值。

Vase被嵌套在Table這個(gè)Prefab中
在Prefab的實(shí)例中進(jìn)行嵌套的操作

我們也可在非Prefab模式下來創(chuàng)建Prefab的嵌套。我們只需要把Prefab資源拖動(dòng)到一個(gè)Prefab實(shí)例下面,編輯器會(huì)在Hierarchy為我們創(chuàng)建一個(gè)疊加了+標(biāo)記的Prefab實(shí)例(+標(biāo)記意味著這個(gè)被添加的Prefab實(shí)例可以撤銷或者應(yīng)用到外部的Prefab中去)。

這里我們和前面介紹的通過實(shí)例來編輯Prefab的操作一樣,可以把這個(gè)修改覆蓋值應(yīng)用到外部的Prefab資源中去。在進(jìn)行覆蓋操作后,+號(hào)標(biāo)記會(huì)消失,它將成為外部Prefab的一部分。

左邊:“Vase”Prefab作為一個(gè)覆蓋操作被添加到Table的實(shí)例下。右邊:“Vase”Prefab被嵌套到“Table”Prefab中去

六、Prefab變體

Prefab變體類似于面向?qū)ο缶幊讨械睦^承的概念。Prefab變體繼承了基礎(chǔ)Prefab的所有屬性,覆蓋Prefab變體中的屬性,會(huì)把屬性覆蓋到基礎(chǔ)Prefab中去。Prefab變體也是一個(gè)會(huì)帶來極大效率提升的新功能。

Prefab變體可以這樣的應(yīng)用場(chǎng)景下使用: 我們有一個(gè)武器的Prefab,為這個(gè)武器創(chuàng)建一個(gè)變體,通過賦予不同的材質(zhì),可以讓武器呈現(xiàn)出不同于基礎(chǔ)Prefab的外觀,例如金屬質(zhì)感,破舊感。對(duì)于基礎(chǔ)武器Prefab的修改,會(huì)影響變體(在變體中覆蓋的屬性不受影響)。比如我們可以通過調(diào)整基礎(chǔ)Prefab的碰撞參數(shù)來修改各個(gè)變體的物理碰撞范圍。

創(chuàng)建Prefab變體

Unity提供了多種方法來創(chuàng)建Prefab變體:

  • 在Project視圖中,右鍵點(diǎn)擊Prefab資源,然后選擇“Create Prefab Variant”。
  • 把一個(gè)Prefab實(shí)例從Hierarchy視圖中拖到Project視圖中,會(huì)彈出一個(gè)對(duì)話框,讓我們選擇是創(chuàng)建一個(gè)新的Prefab還是創(chuàng)建一個(gè)Prefab變體。如果我們選擇Prefab變體的話,就會(huì)基于拖出的Prefab實(shí)例的Prefab資源來創(chuàng)建一個(gè)變體,所有在這個(gè)實(shí)例中的修改,都會(huì)存儲(chǔ)在Prefab變體內(nèi)部
    Prefab變體顯示和Prefab一樣的圖標(biāo),不同的是,圖標(biāo)上有疊加箭頭樣的裝飾圖形。
Prefab變體在Hierarchy視圖中
編輯Prefab變體

在Prefab模式下的Prefab變體的的根節(jié)點(diǎn)顯示著標(biāo)志著是Prefab實(shí)例的藍(lán)色圖標(biāo),本質(zhì)上Prefab變體的內(nèi)核就是一個(gè)Prefab實(shí)例,任何對(duì)這個(gè)變體的修改,都可以覆蓋到基礎(chǔ)Prefab中去。

變體可以覆蓋的類型和相關(guān)限制,與Prefab實(shí)例中修改Prefab是一樣的,具體可參考第三節(jié)實(shí)例覆蓋部分的描述。

例如,選擇“Table with Vase”的根節(jié)點(diǎn),然后點(diǎn)擊Inspector界面中的Select按鈕,編輯器會(huì)幫助選中基礎(chǔ)Prefab資源,正如我們前面所說,這是因?yàn)樵谧凅w中,“Table with Vase“是一個(gè)Prefab實(shí)例。

對(duì)Prefab變體的相關(guān)操作,和實(shí)例覆蓋完全一致。再次強(qiáng)調(diào)一下,所有的Override操作,都是覆蓋到基礎(chǔ)Prefab資源中的,而不是Prefab變體中。

打開"Table with Vase"變體的Overrides界面

七、多層級(jí)應(yīng)用覆蓋值

當(dāng)我們修改一個(gè)嵌套在內(nèi)部的Prefab實(shí)例時(shí)候,在執(zhí)行Override操作的時(shí)候,Unity提供了在應(yīng)用覆蓋的時(shí)候可以選擇覆蓋到不同的Prefab的選項(xiàng),這就是所謂的多層級(jí)應(yīng)用覆蓋。



如果Vase中的根節(jié)點(diǎn)的Scale被修改了,在應(yīng)用覆蓋的時(shí)候,可以選擇是應(yīng)用到Table還是Vase上。

  • 如果選擇了應(yīng)用到Vase上,則修改后Scale會(huì)保存到Vase的Prefab資源中去,進(jìn)而影響到所有的Vase實(shí)例。
  • 如果選擇了應(yīng)用到Table上,修改后的Scale變成Table這個(gè)Prefab內(nèi)部的Vase實(shí)例的值覆蓋,修改后的Scale在Hierarchy或Inspector界面中不會(huì)被標(biāo)記為藍(lán)色的值覆蓋。但是在Table的Prefab模式下,Vase實(shí)例的Scale值,依然標(biāo)記為值覆蓋。這就意味著所有的Table實(shí)例中的Vase實(shí)例都使用了這個(gè)Scale來覆蓋Prefab資源中的值。*而在工程中的其他不屬于Table中的Vase實(shí)例,則不受這個(gè)值的影響。

八、Unpacking Prefab Instance(解除和Prefab的關(guān)聯(lián))

在新版本中的Prefab中,可以通過Unpack Prefab來解除Prefab實(shí)例和Prefab資源之間的連接關(guān)系。Prefab實(shí)例解除連接后,在Hierarchy視圖中的圖標(biāo)顯示為普通GameObject的圖標(biāo)。

新版Prefab系統(tǒng)支持兩種解除連接Prefab資源的方法,點(diǎn)擊Prefab實(shí)例的根節(jié)點(diǎn),在右鍵彈出的窗口中,找到下面的兩個(gè)選項(xiàng):

  • Unpack Prefab

解除當(dāng)前Prefab實(shí)例和Prefab資源的連接關(guān)系。這個(gè)操作對(duì)內(nèi)部嵌套的Prefab是沒有影響的。

  • Unpack Prefab Completely

完全解除關(guān)聯(lián)和舊版本引擎的“Break Prefab Instance”功能類似,一旦執(zhí)行了完全解除關(guān)聯(lián),當(dāng)前Prefab實(shí)例下的所有嵌套Prefab實(shí)例也會(huì)失去和對(duì)應(yīng)的Prefab資源的關(guān)聯(lián)。

九、結(jié)尾

新版的Prefab系統(tǒng)為大家介紹到這里。本文的核心內(nèi)容主要參考自官方的一篇關(guān)于Prefab的文章Prefab手冊(cè)。
寫作本文的過程中,筆者使用的Unity引擎版本是2018.3.b7。操作過程中,仍然出現(xiàn)了一些難以描述的bug。例如嵌套的Prefab在場(chǎng)景里面有顯示,但是Hierarchy視圖中,卻看不到(此時(shí)編輯器控制臺(tái)會(huì)一直報(bào)一個(gè)序列化相關(guān)的錯(cuò)誤)。因此,不建議在正式的商業(yè)項(xiàng)目中使用Unity2018.3的beta版本。

受限于筆者的能力有限,因此難免有偏頗之處,希望朋友們雅正、諒解。

?著作權(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)容

  • 本文節(jié)選自洪流學(xué)堂公眾號(hào)專欄《鄭洪智的Unity2018課》,未經(jīng)允許不可轉(zhuǎn)載。 洪流學(xué)堂公眾號(hào)回復(fù)專欄,查看更多...
    洪智閱讀 10,876評(píng)論 4 5
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,641評(píng)論 19 139
  • 關(guān)于這些技巧這些技巧不可能適用于每個(gè)項(xiàng)目。這些是基于我的一些項(xiàng)目經(jīng)驗(yàn),項(xiàng)目團(tuán)隊(duì)的規(guī)模從3人到20人不等;框架結(jié)構(gòu)的...
    Babybus_Unity閱讀 2,819評(píng)論 2 27
  • 我輕輕地舞著,在擁擠的人群中。你投射過來異樣的眼光,詫異也好,欣賞也罷,并不曾使我的舞步凌亂。因?yàn)榱钗绎w揚(yáng)的,不是...
    只有香如故閱讀 264評(píng)論 0 1
  • 概述 ThreadLocal是一種線程內(nèi)部存儲(chǔ)類。通過他存儲(chǔ)的數(shù)據(jù)在不同的線程操作而互不干擾,類似于各個(gè)線程中都有...
    皮球側(cè)飛閱讀 562評(píng)論 0 8

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