[ Unity 2D ] 教學 #05 – 物件創造、物件銷毀

標籤: , ,

這次來講到物件創造與物件銷毀,我們繼續使用先前的小飛兵專案來教學,這次要做的功能是「按下鍵盤Z發射子彈」並且「子彈超過一定距離時銷毀」,在這次教學中會使用到先前的移動鍵盤事件

創造物件的程式碼如下:

Instantiate(gameObject, transform.position , new Quaternion(0,0,0,0));
//在此物件的位置克隆(複製)一個此物件出來,並且給予旋轉值(0,0,0,0)
  • 名詞解釋
  • Instantiate – 實例化:克隆(複製)一個對象並返回他的實體
    1. 參數1 – 被複製的遊戲物件
    2. 參數2 – 複製出來的物件的位置
    3. 參數3 – 複製出來的物件的旋轉(四元數)

其實說是創造,實際上是複製一個物件,這個被複製的物件可以是場景上的任何一個物件,也可以是project中的「prefab」物件,這個「prefab」在待會會做說明,而旋轉的值如前幾篇提到的四元數,他並不是一個Vector3或Vector2的值,有興趣的話可以Google何謂四元數,在這邊只要全部參數給0就可以了。

為了與先前的Move有所區隔,我們新增一個名叫「Shooting」(射擊)的C#腳本,並拖曳至小飛兵身上。

在這邊提供一個子彈的圖片作為教學使用

新增一個2D Sprite物件將它命名為子彈,並將子彈A這張圖片拖曳給它。

此時我們就可以開始撰寫創造子彈的程式碼了。

開啟Shooting腳本,在Update的地方撰寫按鍵Z發射子彈的程式碼:

public GameObject Bullet;//子彈物件
void Update () {
  if (Input.GetKeyDown(KeyCode.Z))
  {
     Instantiate(Bullet, transform.position, new Quaternion(0, 0, 0, 0));
     //複製子彈物件在物件位置
   }
}

public是公用變數的宣告,我要創造(複製)的物件是子彈,因此我宣告一個公用變數Bullet作為子彈這個物件。

在這邊要多介紹一個Unity的功能,被宣告為public的變數可以在Unity組件視窗中直接修改,如附圖所示,不過預設的只有Unity內建的一些類別跟資料型態可以更改,如int、string、Vector2等等,可以從組件視窗中設定Bullet這個變數所指向的物件,因此我們將場景中的子彈拉到Bullet欄位上,或著點擊欄位右方的圈圈選擇子彈物件,這樣就可以從程式碼獲取子彈這個物件了。

進行測試,剛開始的畫面會像這樣

按下Z鍵之後

創造子彈的功能就完成了,子彈會出現在小飛兵的身上,不過旁邊那子彈有點礙眼,如果將它刪除的話就沒辦法複製物件了,因此又要再講到Unity的一個功能,也就是剛剛提到的prefab。

將子彈物件拖曳至project視窗,會發現project視窗多了一個子彈的方塊,這就是prefab,拖曳進去後,「Project視窗的子彈」與「場景中的子彈」就會形成父子關係,修改project內的子彈時場景中的會跟著修改,但是反過來則不會,這時候點擊場景中的子彈,會發現文字變成藍色,這就表示他連接著project中的prefab,如果是紅色,則表示project中的prefab不見了。

若從場景中修改已經有prefab的物件(名字為藍色字體者),若想將修改的屬性套用至prefab內可以點擊屬性視窗右上方的Apple,反之要還原成prefab的設定時則按下Ravert即可。

這時,本來在小飛兵上的Shooting中的Bullet,就可以改用project中的子彈,而不用場景中的子彈,當點擊Bullet欄位旁圈圈跳出視窗中的Assets,就會看見project視窗中的子彈物件(如附圖)。

這時就可以把場景中的子彈刪除了,再次執行按下Z鍵,就有很正常的子彈出現了。

再來就可以撰寫子彈移動的程式碼了,我們新增一個名為BulletMove(子彈移動)的C#腳本,在Update中加入移動的程式碼

public float Speed = 5;
void Update () {
   transform.Translate(Vector2.up * Time.deltaTime * Speed);
   //每秒向上移動(Speed)單位的距離
}

如果剛剛所說的public,設定一個公用的名為Speed的float變數,作為子彈移動的速度,可以從Unity編輯視窗的組件視窗中修改參數,以便我們進行測試。

將BulletMove拖曳至Project的子彈之上,這樣子彈就有BulletMove這個組件了,再進行一次測試,就會發現子彈很迅速地向上射出去了。

如果覺得速度太快,可以在project的子彈中修改Speed的值。

基本上發射子彈的功能這樣就完成了,但是製作遊戲時有很重要的一點必須注意,就是「不再使用」的物件必須要移除,否則玩家的記憶體會被這些垃圾物件給塞爆,因此再子彈飛出一定距離後就必須銷毀。

在這裡,我設定子彈的Y值大於50或小於-50的時候就自己銷毀,原因是我的遊戲不會用到這麼大的Y值,在BulletMove的Update中再添加幾行程式碼:

if (transform.position .y > 50 || transform.position .y < -50)
{
   Destroy(gameObject);
}
  • 名詞解釋:
  • Destory – 摧毀:將物件(Object)給摧毀,釋放掉它的記憶體
    1. 參數1:被摧毀的物件(Object),由於Object可以是任意類型,因此給予GameObject就會將遊戲物件給移除了

由於這樣看不太出效果,可以先將值改為大於1,執行後會發現射出的子彈在Y>1的時候就會自己銷毀了。

※補充:Instantiate會將複製後的物件傳回,可以使用Object類型去接收它,或著將它轉型成GameObject。

GameObject CloneBullet = (GameObject)Instantiate(Bullet, 
transform.position, new Quaternion(0, 0, 0, 0));

這個使用方式非常常用到,務必要熟悉這種用法。

[ Unity 2D ] 教學 #06 – 碰撞器、觸發器、剛體(一)



相關文章

都是初始化,Awake、Start的差異 當我們要在 Unity 中處理初始化的部分時,大多都是寫在「Start」的函式中,但若寫在「Awake」也能有差不多的效果。 那 Start 跟 Awake 差在哪邊呢? 首先要先看一下Unit...
教學 #11 – Tag(標籤) 在GameObject的屬性視窗中,可以看到上面有個「Tag」屬性,中文稱作為標籤 Tag屬性可以作為分類的用途,例如將食物分為飲料和餅乾等等,在Unity中也可以將物件用Tag分為各種不同的類...
教學 #09 – 獲取Component(組件)資訊 每個GameObject都帶有數個Component組件,而我們自定義的腳本中常有一些需要抓取的資訊,例如角色的血量、速度等等的,就必須抓取物件Component中的一些參數。 Get...
教學 #07 – 碰撞器、觸發器、剛體(二)... ---Rigidbody - 剛體--- 想必第一次看到這詞的人一定會問:「剛體是什麼?」這東西不像碰撞器與觸發器那樣可以從字面上來解讀,想知道完整解釋的話可以查查維基百科。 大...