Unity 3D 裏的碰撞檢測

[Unity 3D] Unity 3D 裏的碰撞檢測

Unity 3D裏兩個碰撞體之間發生碰撞可以用OnCollision族函數和OnTrigger族函數來獲知和處理。Unity官方給出了兩張可發生碰撞的組合表:

Collision detection occurs and messages are sent upon collision
  Static Collider Rigidbody Collider Kinematic 
Rigidbody Collider
Static  
Trigger Collider
Rigidbody 
Trigger Collider
Kinematic Rigidbody 
Trigger Collider
Static Collider   Y        
Rigidbody Collider Y Y Y      
Kinematic Rigidbody Collider   Y        
Static Trigger Collider            
Rigidbody Trigger Collider            
Kinematic Rigidbody Trigger Collider             

Trigger messages are sent upon collision
  Static Collider Rigidbody Collider Kinematic 
Rigidbody Collider
Static  
Trigger Collider
Rigidbody 
Trigger Collider
Kinematic Rigidbody 
Trigger Collider
Static Collider         Y Y
Rigidbody Collider       Y Y Y
Kinematic Rigidbody Collider       Y Y Y
Static Trigger Collider   Y Y   Y Y
Rigidbody Trigger Collider Y Y Y Y Y Y
Kinematic Rigidbody Trigger Collider Y Y Y Y Y

不過,生搬硬背顯然不是一個有理想的死程應該做的事情。那麼,要如何理解和記憶Unity 3D裏的碰撞發生條件呢,歸根結底只要理解了以下五個概念就搞定了:

Collider

Rigidbody

Static

Kinematic

Trigger

Collider——很簡單,就是碰撞盒,有碰撞盒纔有碰撞,所有碰撞的參與者都必須要有至少一個碰撞盒才行;

Rigidbody——剛體,當剛體存在時物理引擎就會介入,對於引擎來說,碰撞必須要有剛體參與(原因後述),但是並不要求碰撞的雙方都是剛體,只要動的一方是剛體就OK,如果雙方都有位移或者旋轉,那麼只要有一方是剛體就OK;

Static——這其實只是一個描述,或者說概念,任何不是剛體的物體,引擎都認爲它永遠是Static的,即靜止的,哪怕它正在發生位移或者旋轉;而剛體,引擎認爲它是“能運動的”,也就是說,剛體雖然可以保持靜止的狀態,但是一旦發生位移或者旋轉,引擎就會認爲它動了;對於兩個靜止的物體,引擎認爲他們不會發生碰撞,也就不會處理他們之間碰撞盒的任何交疊,這裏包括兩個非剛體,也包括一個保持靜止的剛體和一個非剛體。這就是碰撞發生的雙方中運動的那一方必須要是剛體的原因。

Kinemtic——這是一個描述,同時也是Rigidbody的一個屬性。被標記爲Kinematic的剛體就成爲了一個純運動學物體,這意味着它不再受外力作用,它的運動狀態直接由位置和旋轉來決定。當然,一個Kinematic的剛體還是可以對外產生作用力的,也就是說,它可以推動其他剛體,但是其他剛體對它無可奈何。

Trigger——這也是一個描述,同時是Collider的一個屬性。被標記爲Trigger的碰撞盒不再具備物理特性,這與Kinematic不一樣,Kinematic的剛體仍就是一個物理體,而Trigger只代表一個區域,或是一個引子(這取決於它在碰撞中擔當的角色,在碰撞中,如果它是運動的那一方,那麼它就是一個引子,只要它碰撞到了任何物體,不論靜止還是運動,都會被觸發;如果它是靜止的那一方,那麼它就是一個區域,所有進入此區域的運動物體都會觸發它,這裏的“運動”不是單純的位移或者旋轉,參照Static的定義)。

好了,下面拿着這五個概念對照的看看Unity官方提供的表單。

先看Collision表,Collision是物理引擎管轄下的碰撞,即便是你不處理OnCollision族函數,物理引擎也會爲碰撞雙方計算作用力和作用力下的運行。由於Trigger標記下的物體不再是物理體,任何標記爲Trigger的物體都不會觸發Collision。物理碰撞的發生必然是有一方在運動,因此如果雙方都被引擎認爲是靜止的物體,是不可能發生Collision的,因此雙方都是非剛體(表中的Static Collider)時無法觸發Collision。 這裏還有一個小問題,光從Collision表裏是看不出來的,那就是在Static Collider和Rigidbody Collider之間,即便Collision表裏畫的是對鉤,當碰撞裏有位移或者旋轉的那一方是Static Collider而不是Rigidbody Collider的時候,Collision是不會觸發的哦,原因很簡單,就是前面說的引擎認爲物體靜止的問題,沒有位移或者旋轉的Rigidbody是靜止的,而非剛體也是靜止的,兩個靜止的物體無法發生碰撞 。至於Kinematic Rigidbody Collider,由於它本身不會受外力作用,而Collision是要能夠產生物理作用力的,所以只有當能夠受外力作用的物體跟它相撞時纔會觸發Collision,因此,沒有作用力概念的Static Collider和不受外力作用的Kinematic Rigidbody Collider是無法跟它產生Collision的。

再看Trigger表,要觸發Trigger就至少要有一個被標記爲Trigger的碰撞盒存在,因此雙方都沒有被標記Trigger時,Trigger是不會觸發的。即便有被標記爲Trigger的物體存在,如果雙方都被引擎認爲是靜止狀態,同樣不會觸發Trigger(還是那個道理,兩個被引擎認爲靜止的物體,是無法發生碰撞的),因此Static Collider跟Static Trigger Collider之間,兩個Static Trigger Collider之間,都不會觸發Trigger。跟Collision表一樣,這裏也有一個小問題光從表裏看不出來,就是當Static Collider遇上Rigidbody(Kinematic)時,不管誰是Trigger,運動的一方必須要是Rigidbody(Kinematic)才能觸發Trigger,道理同上 。

唯一一個例外情況:

如果雙方初始化在了一起,也就是說雙方初始化出來碰撞盒就發生了交疊,這時候物理引擎網開一面,對於Collision來說,只要雙方都不是Trigger,且有一方是非Kinematic的Rigidbody(也就是說Collision表裏畫了對鉤的組合),就必然會發生一次Collision,對於Trigger來說,只要雙方有一方是Trigger,且有一方是Rigidbody(Kinematic)(亞也就是Trigger表裏畫了對鉤的組合),那麼就必然會觸發一次Trigger。當然這僅限初始化的那一幀,之後就一切迴歸正軌。

不過Unity 3D在這裏有一個bug,當雙方一個是非Kinematic的Rigidbody,另一方是Static Collider也就是非剛體,且碰撞盒在初始化時就交疊在了一起的話,除了一開始的那一幀會觸發Collision外,之後剛體不動而非剛體動,仍有一定機率會觸發Collision(按規則說是不能觸發的),具體表現就是非剛體可以推着剛體走。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章