2012年11月8日 星期四

關於 Collider 與 Ragidbody (碰撞體與剛體) 的碰撞偵測與怎麼做

(最近開始試用 Unity3D, 寫一下心得筆記, 但先說明不代表我的觀點是完全正確的, 畢竟我才用沒兩小時...)


關於 Collider 與 Ragidbody 的碰撞偵測與怎麼做

p.s. 一開始我有些不明白這兩個的差異, 我知道 Collider 是用在碰撞偵測, Ragidbody 是用在物理計算的需求, 但為什麼單純兩個有 Collider 的物體相撞沒有任何事件 (OnTriggerEnter)發生?

研究了一下, 此簡要設定碰撞事件的步驟:

1. 每個能被撞倒的物體(範例是隕石與子彈)都要有一個 Collider 元件 (檢查一下 Collider 元件有被啟動, 並調整好適合的大小/位置)

2. 每個移動(要去撞人家)物體, 除自己也要有 Collider 外, 還需附加 Ragidbody 元件(*)
   a) 先點選要附加元件的 GameObject
   b) Menu->Component->Physics->Ragibody
   c) 暫時不考慮重力加速度, 核銷 Ragibody 參數的 'Use Gravity' checkbox
  
NOTE: (*)
擁有 Ragidbody 的物體才會即時對場景中的每一個 Colliders 做偵測(要去撞人家), 沒有 Ragidbody 的物體, 儘管也許他能藉由程式碼操作被移動, 但 Unity3D 不考慮對其他的 Colliders 做偵測 (為了加速吧).

例如: 場景中有 A B C  三個物件, A 為 Ragidbody, B/C 非 Ragidbody,  則 Unity3D 偵測  A<->B, A<->C 有沒有碰撞, 不偵測 B<->C

所以下面說法是正確的:
                 
場景中 "只有" 兩個移動物體(各有 Collider), 只要一個有設 Ragidbody 就足夠發生碰撞了!


3. 隕石(有加入 Ragidbody 元件)的 Collider 參數中, 核選 'Is Trigger' checkbox(**)
  
   在 GameObject 物件中加入

public class meteor : MonoBehaviour {
   ...
   void OnTriggerEnter(Collider other)
   {
//      if (other.tag == "bullet")          // 物件參數裡有指定 Tag
        if (other.name == "Bullet(Clone)")  // 用類別的名字
        {
            print("hit by bullet");    
        }
   }
}


   處理被碰撞時做什麼事, 注意: OnTriggerEnter 兩個相撞物件各自都會呼叫

public class bullet : MonoBehaviour {
   ...
   void OnTriggerEnter(Collider other)
   {
        print("OnTriggerEnter: " + other.name + " tag=" + other.tag);
        ...
   }
}


NOTE: (**)
這表示此碰撞體為一個觸發器, 產生碰撞事件, OnTriggerEnter/Exit/Stay(Collider other) 會被呼叫, 時此 Ragidbody 物件不會加入物理引擎做運算(彈跳 etc).(***)

4. 移動中隕石與子彈如果發生碰撞各自 OnTriggerEnter 就被呼叫了.
    (實際只要選擇其中一個處理即可 )


NOTE: (***)
如果 'Is Trigger' 不用, 則會 Ragidbody 有物理作用, 此時碰撞改用 OnCollisionEnter/Exit/Stay(Collision collision)
注意此處傳遞的是 Collision 不是 Collider!
 
以上這樣子就明瞭了, Collider 的 'Is Trigger' 主要的用途了, 他一般是使用在類
似進入/離開/停留一個區域要'觸發'事件, 在那種不需要有物理推擠的時機.

P.S. 一個 GameObject 可以附加好幾個 Collider, 所以可以按需求不同的作用一起發
生.