【Unity】物理碰撞實驗


這幾天為了准備面試,所以決定對平時學習中的盲點掃盲一下,首先想到的就是物理碰撞。以前沒有好好研究過,一直模糊不清,到底什么條件下才可以產生物理碰撞呢?只要其中一個有Rigidbody就可以了嗎?所以進行了下面的實驗。

以下內容參考了Unity聖典的組件手冊

----------------------------------------------------------------------------分割線--------------------------------------------------------------------------------

首先查找資料,發現Unity組件文檔中將碰撞體分為了3個類型,如下所示。


Static Collider 靜態碰撞器

 

These are GameObjects that do not have a Rigidbody attached, but do have a Collider attached. These objects should remain still, or move very little. These work great for your environment geometry. They will not move if a Rigidbody collides with them.

指的是沒有附加剛體而附加了碰撞器的游戲對象。這類對象會保持靜止或者很輕微的移動。對於環境模型十分好用,當和剛體碰撞時而不會移動。


 

Rigidbody Collider 剛體碰撞器

 

These GameObjects contain both a Rigidbody and a Collider. They are completely affected by the physics engine through scripted forces and collisions. They might collide with a GameObject that only contains a Collider. These will likely be your primary type of Collider in games that use physics.

指的是同時附加了剛體和碰撞器的游戲對象。通過腳本的力量和碰撞完全受物理引擎的影響。可以和只包含碰撞器的游戲對象碰撞。將會成為你游戲中使用物理效果的基本類型碰撞器。


Kinematic Rigidbody Collider 運動學剛體碰撞器

This GameObject contains a Collider and a Rigidbody which is marked IsKinematic. To move this GameObject, you modify its Transform Component, rather than applying forces. They're similar to Static Colliders but will work better when you want to move the Collider around frequently. There are some other specialized scenarios for using this GameObject.

指的是同時包含碰撞器和剛體,並且激活IsKinematic的一類游戲對象,要移動這類游戲對象,要修改它的Transform組件(指的是position和rotation這類屬性),而不是用力。它們很像靜態碰撞器,不過如果你想要不停地到處移動碰撞器,它們會更好用。這類游戲對象還有許多其他的獨特使用情景。

運動學剛體碰撞器是個非常懶惰和霸道的家伙,它碰到其他碰撞器完全沒有反應(其實還是有點反應,會觸發一些碰撞函數的,后面有解釋)。它不受力、重力或扭矩的影響。可以通過設置Transform 的position和rotation來准確的操作它們或者讓它們動起來,但是,它們可以和其他的非運動學剛體互相作用。對於放在運動學剛體碰撞器上面的剛體,會受到運動學剛體施加的摩擦力。



還有一類叫做角色控制器。

 

Character Controllers 角色控制器

 

You use Character Controllers if you want to make a humanoid character. This could be the main character in a third person platformer, FPS shooter or any enemy characters.

如果想制作一個類似人的角色那就使用角色控制器。這可以是第三人稱平台游戲、第一人稱射擊游戲的主要角色或任何敵對角色。

These Controllers don't follow the rules of physics since it will not feel right (in Doom you run 90 miles per hour, come to halt in one frame and turn on a dime). Instead, a Character Controller performs collision detection to make sure your characters can slide along walls, walk up and down stairs, etc.

這類控制器不遵循物理規則因此它感覺上不對勁(在Doom中,你跑到了90英里每小時,然后馬上停下而且可以極快的轉身)。不過,角色控制器執行碰撞檢測以保證你的角色可以沿着牆滑動,上下台階等等。

Character Controllers are not affected by forces but they can push Rigidbodies by applying forces to them from a script. Usually, all humanoid characters are implemented using Character Controllers.

角色控制器不受力影響(但是重力效果還是有的)但是可以被由代碼施加的力推動。通常,所有類似人的角色都用角色控制器來執行。

Character Controllers are inherently unphysical, thus if you want to apply real physics - Swing on ropes, get pushed by big rocks - to your character you have to use a Rigidbody, this will let you use joints and forces on your character. Character Controllers are always aligned along the Y axis, so you also need to use a Rigidbody if your character needs to be able to change orientation in space (for example under a changing gravity). However, be aware that tuning a Rigidbody to feel right for a character is hard due to the unphysical way in which game characters are expected to behave. Another difference is that Character Controllers can slide smoothly over steps of a specified height, while Rigidbodies will not.

角色控制器本身不具物理特性,因此如果想應用真正的物理作用——在繩上搖擺,被大石頭推動——到你的角色,必須用剛體,這會允許你把鉸鏈或力用到你的角色上。角色控制器永遠沿Y軸對齊,因此,如果你的角色需要在空間中改變方向那也必須用到剛體(比如在變化的引力控制下)。但是,要意識到調整一個剛體在角色上表現自然是很難的,因為游戲角色自身的非物理特性總想表現出來。另一個困難是,角色控制器可以從特定高度的台階上平滑地滑下,而剛體不會。

 

The Controller does not react to forces on its own and it does not automatically push Rigidbodies away.

控制器不會對加在它自身上的力做出反應,也不會自動推開其他剛體。(這里我沒有明白,因為我實驗過在一個剛體內部實例化一個控制器,剛體是會被彈開的。如果有人懂請告訴我,不勝感激!)

If you want to push Rigidbodies or objects with the Character Controller, you can apply forces to any object that it collides with via the OnControllerColliderHit() function through scripting.

如果想讓角色控制器推開其他剛體或者對象,你可以在對象附加的腳本中添加OnControllerColliderHit()函數,這樣對它們施加力就能夠產生碰撞。

也就是說,角色控制器可以使用物理效果影響其他對象,前提是你自己寫了腳本。

On the other hand, if you want your player character to be affected by physics then you might be better off using a Rigidbody instead of the Character Controller.

而角色控制器不能通過物理效果被其他對象影響。因此,如果你想讓你的游戲角色被物理效果影響,那就最好使用剛體而不是角色控制器。


 


角色控制器和運動學剛體有點像,因為它們都不受力的作用(運動學剛體更像是一個剛體,只是不會受到其他任何外力的影響,就像是古代的國王,雖然和普通平民一樣都是人,但是只能他欺負別人,別人無法欺負他;而角色控制器本身就不具有物理特性,不可以推開別人(除非寫了自己的腳本),也不會被別人影響,只是它可以執行碰撞檢測)。但是也有幾點不同的地方。首先,運動學剛體是無法通過代碼施加力的作用來推動,但是角色控制器是可以的。第二,運動學剛體不會受到重力的作用,而角色控制器是有重力效果的。其次,角色控制器只能沿Y軸旋轉,也就是人永遠都是直立狀態,不會因為受到力的作用就趴下啦,而剛體是可以的。第三,角色控制器可以從特定高度台階上平滑地滑下,而剛體不會。



說了這么多,暈了吧,恩,我也暈了。所以我們來做下實驗!我們通過一個最簡單的場景,即一個平行光、一個平面、兩個正方體來試驗一下。通過給兩個正方體添加不同的碰撞體類型來觀察是否會發生碰撞。


下面的實驗中,一個正方體保持靜止,另一個正方體我們通過代碼來控制運動,即上下左右方向鍵可以控制它的上下左右運動。



移動的靜態碰撞器VS靜止的靜態碰撞器

沒有任何碰撞效果。這在意料之中,因為沒有一個添加了Rigdbody屬性,肯定不會碰撞啦!


移動的靜態碰撞器VS靜止的剛體碰撞器

沒有任何碰撞效果。
這個結果有點意外,明明一個已經添加了Rigdbody,為什么還是無法發生碰撞呢?這是因為添加了Rigdbody的正方體是靜止的,而靜止的剛體會進入休眠。好吧,又遇到了新的名詞, 剛體休眠。例如,當一個正方體掉到地板上靜止后就會進入剛體休眠。剛體休眠完全自動發生。只要剛體的速度低於sleepAngularVelocity和sleepVelocity,該剛體就會開始休眠。其空閑一些幀后,就會被設置成休眠狀態。處於休眠狀態中的物體,不會再對其進行碰撞檢測和模擬。這會節約大量的CPU開銷。這就解釋了為什么我們這個實驗里沒有碰撞發生,因為它睡覺去了,而那個移動的靜態碰撞器又無法喚醒它,所以它壓根就不知道有人碰到了自己。這里又有一個問題了,那么什么情況下可以喚醒已經休眠了的剛體呢?有4中情況:
  • 被施加了外力,也就是說在代碼里使用了AddForce;
  • 剛體的屬性發生了變化;
  • 和它通過關節連接的剛體發生了移動,因為連帶關系,所以它也被喚醒了;
  • 被其他剛體碰撞器碰撞。但是,只有處於運動狀態中的剛體(包括普通的剛體碰撞器和運動學剛體碰撞器)能喚醒休眠中的剛體,靜態碰撞器不能喚醒休眠中的剛體。即如果你將一個靜態碰撞器(沒有和任何剛體綁定過)綁定到處於休眠中的剛體,或者將靜態碰撞器抽離處於休眠中的剛體時,這個休眠中的剛體是不會被喚醒的。但是如果你將一個運動中的剛體從它所屬的且處於休眠狀態中的頂層剛體移出時,處於休眠中的剛體將會被喚醒,且會在圖形更新里被重新正確的計算。
最后這句話時什么意思呢?我們再做兩個實驗好了。還是兩個正方體,我們將一個正方體放在另一個的上方。

在兩個實驗里,上方的正方體都是普通的剛體碰撞器,而下方的正方體有所不同,我們可以通過代碼移動下方的正方體使得它從上方正方體的下面移開。
第一個實驗里,下方的正方體是一個靜態碰撞器。當我們移開后,上方的正方體直直地下落,直到碰到地板,期間沒有任何物理效果(除了重力效果)。
第二個實驗里,下方的正方體是一個運動學剛體碰撞器。當我們移開下方正方體的過程中,我們會發現上方的正方體會受到摩擦力的左右而也發生了一定移動,當兩個正方體完全分離后,上方的正方體晃動着掉到了地板上(因為之前受到了摩擦力)。
好了,有點明白了嗎?靜態碰撞器是不會喚醒休眠剛體的(第一個實驗),而運動學剛體由於會對剛體產生力的作用而可以喚醒休眠中的剛體。

再提一個問題,如果上面的正方體是運動學剛體碰撞器呢?那么無論下面是什么碰撞器它都沒有反應,因為它是國王啦,不受到任何外力的影響,包括重力!


移動的剛體碰撞器VS靜止的靜態碰撞器

有碰撞效果,具體為:對於移動的剛體碰撞器在遇到靜態碰撞器后會產生物理效果,如反彈、無法前進等;對於靜止的靜態碰撞器,會產生輕微的碰撞效果,如輕微的晃動,但是不會移動。


移動的剛體碰撞器VS靜止的剛體碰撞器

有碰撞效果,對於兩個物體都出現正常的物理效果,如反彈等。


移動的靜態碰撞器VS靜止的運動學剛體碰撞器

沒有任何碰撞效果。運動學剛體碰撞器是不受到任何外力作用的。


移動的運動學剛體碰撞器VS靜止的靜態碰撞器

沒有任何碰撞效果。運動學剛體碰撞器是不受到任何外力作用的。


移動的運動學剛體碰撞器VS靜止的剛體碰撞器

有碰撞效果,但僅剛體碰撞器有碰撞效果,如反彈等,運動學剛體碰撞器不受力的作用。


移動的剛體碰撞器VS靜止的運動學剛體碰撞器

有碰撞效果,但僅剛體碰撞器有碰撞效果,如反彈等,運動學剛體碰撞器就像一堵牆一樣一動不動。


移動的運動學剛體碰撞器VS靜止的運動學剛體碰撞器

兩個太上皇相見了會怎么樣呢?沒有任何反應……就像兩個靜態碰撞器一樣。



下面,將一個正方體換成角色控制器,繼續實驗。



移動的靜態碰撞器VS靜止的角色控制器

沒有任何碰撞效果。


移動的剛體碰撞器VS靜止的角色控制器

有碰撞效果,剛體碰撞器遇到角色控制器后會發生反彈,無法繼續前進,而角色控制器沒有任何效果。


移動的運動學剛體碰撞器VS靜止的角色控制器

沒有任何碰撞效果,會互相穿過。


移動的角色控制器VS靜止的靜態碰撞器

沒有任何碰撞效果,會互相穿過。


移動的角色控制器VS靜止的剛體碰撞器

有碰撞效果,剛體碰撞器被彈開。


移動的角色控制器VS靜止的運動學剛體碰撞器

沒有任何碰撞效果,會互相穿過。



碰撞信息和觸發信息


對於碰撞時是否會發出碰撞函數(或觸發信息),可以見下表。碰撞信息是指OnCollisionEnter() OnCollisionStay()和 OnCollisionExit()這三個函數,而觸發信息指的是OnTriggerEnter() OnTriggerStay和OnTriggerExit()三個函數。


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 Y

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM