預製體
Prefab
Prefab的作用是保存一個GameObject的外觀、組件及其屬性,在需要用的時候方便快捷的將其複製,並且統一管理。Prefab作爲被序列化的GameObject保存在硬盤中,它既可以作爲佈置場景時使用的模板物體,又可以作爲在腳本中動態生成物體的模板。
要創建Prefab,可以先在場景中創建想要作爲Prefab的GameObject,在Hierarchy中選中它,然後將它拖動到Project面板中。一般來說,我們會先將空物體保存爲Prefab,然後再給Prefab設置用於外觀或邏輯的子物體。
由於Prefab物體會經常在遊戲進程中被動態調用,這些需要在代碼中動態調用的Prefab應該被放到Resources文件夾裏。
在編輯模式下將Prefab從Project面板拖動到Hierarchy面板或Scene面板,來以這個Prefab爲模板創建一個GameObject。如果一個GameObject是基於Prefab生成的,它在Hierarchy中的圖標和名稱會被顯示爲藍色,且最右方有一個”>”符號。
Prefab可以作爲一個GameObject被賦值給屬性,如:
class BulletShooter : MonoBehaviour
{
[SerializeField]
private GameObject m_bullet;
void shoot(Vector3 direction)
{
if(m_bullet == null) throw new ReferenceNotInitialized();
GameObject bullet = Instantiate(m_bullet, transform.position, Quaternion.identity);
bullet.getComponent<Bullet>().MoveTowards(direction);
}
}
在Inspector中我們可以將Prefab拖動賦值給m_bullet屬性,這樣之後使用Instantiate函數時就可以以預製體爲模板創建物體了。
除此之外,我們還可以直接通過文件夾系統來直接獲取Prefab,如下:
class PlayerInstaller : MonoBehaviour
{
private void Start()
{
GameObject player = Resources.Load("Player/Player_Blue") as GameObject;
Instantiate(player);
}
}
以一個Prefab爲模板生成的GameObject是與該Prefab綁定的,每當Prefab被修改,GameObject都會被同步修改。因此每一個在遊戲中多次出現的GameObject都應該製作爲Prefab。
與模板的Prefab相比,圖中Animation是新附加的Component,具有一個加號標識。Capsule Collider是被刪除的Prefab,具有一個減號標識。而Position和Rotation是修改過的屬性,它們顯示爲粗體。我們可以通過Overrides功能將新增、刪減、修改過的組件和屬性重載到Prefab中:
在Overrides面板中可以看到修改過的屬性,我們可以點擊Revert All來取消所有改動或點擊Apply All來應用所有改動,或者在該面板中點擊屬性,對該屬性單獨進行Revert或Apply操作。
在Project面板選中Prefab後可以在Inspector面板看到該Prefab的所有組件,我們可以直接在這裏修改組件的參數,但不能更改Prefab的子物體。如果要修改Prefab的結構,在Inspector面板點擊"Prefab"->"Open"或在Hierarchy面板點擊GameObject右側的”>”符號進入Prefab編輯界面。
在該界面中對Prefab做的所有改動會直接應用到Prefab上,不再需要點擊Apply。
在該界面中可以對Prefab的子物體進行修改,包括子物體的樹型結構、座標、組件和屬性等。
Prefab Varient
在Project面板中右鍵選擇一個Prefab,在右鍵菜單中點擊’Create"->"Prefab Variant"可以生成該預製體的一個分支,預製體分支也可以生成分支的分支。
預製體分支的邏輯在於:
每當一個屬性在Prefab Variant中而非Prefab中被修改,這個屬性就會被設置爲分支屬性。
對一個分支屬性來說,Prefab Variant中的修改不會應用到它的樹幹Prefab上,同時,在Prefab中的修改也不會應用到以它爲模板的Prefab Variant上。
對一個非分支屬性來說,在Prefab中進行修改,會應用到以它爲模板的Prefab Variant上。
例子:在設計一套敵人系統時,我希望兩個敵人的移動屬性保持一致,但其他屬性略有不同,這時我就可以把不同的屬性設置爲分支屬性,讓兩種敵人的屬性略有區別,但是在調整移動屬性時可以對非分支屬性進行修改,這樣就可以一次性應用到所有不同的敵人上。
取消Prefab
對一個以Prefab爲模板的GameObject點擊右鍵菜單可以找到"Unpack Prefab"和"Unpack Prefab Completely"功能。它們的作用都是取消GameObject和Prefab的綁定,取消綁定後,對Prefab的改動不再應用到這個物體。
若父物體和子物體都是Prefab,對父物體使用Unpack Prefab功能會導致父物體取消與Prefab的綁定,但子物體仍保留對Prefab的綁定。而對父物體使用Unpack Prefab Completely功能時,父物體和子物體都將取消與Prefab的綁定。
在Project面板中刪除一個Prefab或Prefab Variant,會自動解除所有以它爲模板生成的GameObject,這麼做之後GameObject的名稱會顯示爲黑紅色。