皮皮特別喜歡玩紙團,我也特意詢問了幾個養貓的朋友,發現貌似所有的貓都天生對紙團沒有抵抗力。無聊時抽出一張紙,揉成一團,咻一聲扔出去,皮皮就會變成一道閃電跟著飛出去,撿到紙團又叼回來。時間久了,即使我手上沒有紙團,只是用嘴發出咻咻咻的聲音,皮皮也會兩眼冒金光四處張望尋找紙團的蹤跡,屢試不爽。
我:「老皮,家裡沒紙巾了,以後沒有紙團玩了。」
皮皮瞪大了圓溜溜的雙眼,半晌,擠出一句話:「你們公司不發紙巾嗎?」天雷一聲響,我被眼前這隻貓雷倒了。
我:「公司一個月就發一包紙巾,哪夠你玩的!!!我一張紙巾撕成兩半用都不夠。」
皮皮跳到貓碗旁邊瘋狂扒拉空氣。
我:「你這是幹嘛?」
皮皮:「防止貓糧被偷,買不起紙巾了,貓糧要保住!」
我:「別扒拉了,我給你做了個無限紙團噴射機。」
我打開Unity,點擊運行。皮皮:「哇,我要學這個!」
8.2 預設是什麼我:「上面這個無限紙團噴射機的製作原理很簡單,就是事先製作一個紙團模型預設(prefab),然後實例化這個預設得到紙團的GameObject,再給紙團一個速度,讓紙團飛出去。」
皮皮:「之前聽你提到過預設,預設到底是什麼呀?」
我:「預設,單詞叫prefab,其實從這個單詞已經可以看出預設的含義。pre詞根,是提前、預先的意思,fab,動詞,是製造、製作的意思,所以從字面看,prefab就是預先製作的意思,也有人叫它預製體。」
預設文件,實質上是一個描述文件,它記錄了它所引用的資源、組件和數據。加載預設時,Unity會幫我們解析它所依賴的資源、腳本和數據,載入到內存中,最終得到預設所包裝的遊戲對象,之後,我們就可以通過實例化預設重複使用這個遊戲對象了。
皮皮:「有點抽象。」
我打開工程目錄,「我先給你看個預設文件。」使用文本編輯器(比如notepad++)打開.prefab文件。打開後我們可以看到裡面的內容,如下:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3921411617931140026
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8079028440690224108}
m_Layer: 0
m_Name: PrefabTest
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8079028440690224108
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3921411617931140026}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}皮皮:「我看到了兩個熟悉的東西:GameObject和Transform。」
我:「觀察力不錯哦。嘛,單看這個文件,我們就可以猜到它是一個帶著Transform組件的GameObject,並且還可以知道具體的參數數據。」
皮皮:「文件開頭的%%YAML 1.1是什麼意思,是壓馬路的意思嗎?」
我:「哈哈哈哈,YAML全稱是Yet Another Markup Language,直譯就是另一種標記語言的意思,是人們發明的一種語言格式,用它很適合描述序列化信息。所以呢,預設文件本身是一個描述文件,記錄了它所引用的資源、組件和數據。」
我們可以把這個預設拖到場景中(實例化),可以看到,它帶著一個Transform組件,其中Position、Rotation、Scaale數據是從預設中解析出來的。
8.3 預設的製作皮皮:「這個預設是怎麼製作的呢?」
預設的製作很簡單,以製作一個正方體的預設為例。在Hierarchy視圖中右鍵點擊菜單3D Object - Cube。
得到一個正方體Cube。
把它拖到Assets目錄中的某個文件夾中,比如Resources文件夾。
這樣,預設文件就製作成功了。
皮皮:「又是用滑鼠拖動這樣的操作。」
我:「你要多練習練習滑鼠,身為一隻貓,不能害怕滑鼠。」
皮皮抓起滑鼠一頓啃。
8.4 預設的修改皮皮:「預設的製作我學會了,如果我想修改預設重新保存怎麼辦?」
我:「這個也很簡單,現在帶你進入神秘世界。」
皮皮:「微信搜索公眾號 [愛上遊戲開發],回復 「資料」,免費領取 200G 學習資料!"
8.4.1 Open Prefab——進入神秘世界在Project視圖中,選中預設文件,然後在Inspector視圖中點擊Open Prefab。
8.4.2 退出神秘世界此時會進入一個神秘的世界。
我們在這個世界裡做的任何修改,都會立刻被序列化到.prefab文件中。比如修改一下Position的x坐標為3。
此時使用文本編輯器打開.prefab文件,即可看到剛剛的修改已經被序列化到文件中了。
皮皮:「怎麼回到原來的世界呢?出口在哪裡?」我:「Hierarchy視圖左上角那裡有個小箭頭,那裡就是出口。」
8.4.3 Overrides——重載預設我:「另外,也可以點擊Scene視圖左上角的Scenes。」
退出後,我們可以看到剛剛的修改是生效的。
修改預設,還有另外一種方式,就是Overrides。將物體拖到場景中(實例化),此時做一下修改,比如把Box Collider組件禁用。
然後點擊Overrides。
此時會顯示所做的修改,點擊Apply All即可重載預設(覆蓋預設)。
皮皮:「Apply All按鈕左邊的Revert All是什麼作用?」
我:「又要教單詞啦,revert,看詞根,re詞根,是向後、相反、回的意思,vert詞根,是轉的意思,組合起來,就是轉回來,就是恢復回原來的意思,兩個字,還原。」
皮皮:「英語過六級的人都喜歡這樣分析詞根嗎?」
我:「不管學什麼,學習方法很重要,好的學習方法可以提升效率,縮短學習時間,我不能讓你在一個月內學會遊戲開發,但是我可以教你好的學習方法,讓你終生受益。」
皮皮搶過滑鼠,點擊了Revert All,說:「真囉嗦,實踐是檢驗真理的唯一標準,測試一下Revert All。」此時,Box Collider回到了原來激活的狀態。
8.5 預設的繼承8.5.1 為什麼要設計預設的繼承我指著預設接著說,「Unity2018之後,預設引入了繼承的概念,可以像類一樣繼承。」
皮皮:「為什麼要弄預設繼承呢?」
我:「舉個應用的場景,假設我現在做了一隻白貓預設,我想再做三隻不同顏色的貓,他們只是顏色不同,其他都和白貓相同,我可以讓這三隻不同顏色的貓都繼承白貓,然後分別修改顏色即可。當我給白貓加了個鈴鐺,這三隻不同顏色的貓也會自動具有鈴鐺,因為它們都繼承了白貓,我不需要挨個給這三隻貓再加鈴鐺了。」
皮皮:「作為一隻貓,我有權利告訴你,貓其實不大喜歡戴鈴鐺。」我:「哈哈哈,平時也沒讓你戴鈴鐺。」
8.5.2 如何製作變種預設
實踐一下預設的繼承吧,以剛剛的Cube預設為例。我們把它再一次拖入Resources文件夾。
8.5.3 修改基預設此時會彈出提示框詢問是要創建一個新的原始預設(Original Prefab)還是一個變種預設(Prevab Variant),點擊Prevab Variant。
此時便成功創建了一個變種預設Cube Variant,它是繼承Cube的。
如果此時你用文本編輯器打開Cube Variant.prefab,就會發現它的結構和Cube.prefab是有差異的。
現在,我們修改基預設,打開Cube.prefab。
8.6 預設的嵌套給Cube加一個Sphere子節點。
調整Sphere的坐標到Cube的下面。
退出神秘世界。
此時拖動變種預設Cube Variant到場景中,看它是否也自動多了個Sphere子節點。
可以看到,Cube Variant也自動多了一個Sphere子節點。
除了預設繼承,預設還可以嵌套。
皮皮:「這又是什麼高級用法?」
我:「還是給你舉個應用例子好了。假設現在我做了一個鈴鐺預設,然後我又做了一隻貓、一隻狗、一隻熊三個預設,我給貓、狗、熊都戴上鈴鐺,事實上,就是把鈴鐺預設分別嵌套在它們預設裡。此時,我想統一調整鈴鐺的大小,我只需調整鈴鐺預設本身即可,不需要分別去調整貓、狗、熊的鈴鐺,因為它們其實是直接引用了鈴鐺預設。」
下面實際操作一下。先分別創建兩個預設:Cube、Sphere。
打開Sphere。
將Cube拖到Sphere子節點中。
此時便完成了預設嵌套:Cube嵌套在Sphere中。
退出Sphere。
打開Cube。
調整Scale的y為3,此時變成了一個長方體。
退出Cube。
實例化Sphere,可以看到,嵌套在Sphere中的Cube也自動變成長方體了。
皮皮:「如何這個時候調整Sphere中的Cube,會不會影響原來的Cube。」
我:「看操,如果直接調整Sphere中的Cube,再點擊Overrides - Apply All的話,會影響到原來Cube,因為這個Cube是原來Cube的引用,如果想要不影響到原來的Cube,就要把Sphere中的Cube弄成變種預設。」
操作如下:把Sphere中的Cube拖到Resources文件夾中。
此時會彈出循環框,點擊Prefab Variant(變種預設)。
此時Sphere中的Cube就是一個變種預設了Cube Variant,此時Sphere中的Cube只會影響Cube Variant,不會影響原來的Cube。當然,如果沒有執行Overrides,那變種預設還是繼承基預設的數值的。