前言
Unity 中內(nèi)置了一套完成的物理引擎,能夠完成現(xiàn)實世界的近似模擬。而在 Unity 物理引擎中,剛體組件和碰撞體組件則是無法避開的,剛體組件是讓物體產(chǎn)生物理行為的組件,而碰撞體組件則是讓剛體與物體產(chǎn)生碰撞的組件,今天就來簡要認識一下這種組件吧。
前排提醒:本文僅代表個人觀點,以供交流學習,若有不同意見請評論留言,筆者一定好好學習,天天向上。
閱讀此文章時,若有不理解的地方,推薦觀看本文列出的參考資料來對照閱讀。
Unity 版本[2019.4.10f1] 夢小天幼 & 禁止轉載
視頻講解:
詳解Unity的剛體和碰撞體_BiLiBiLi
掌握基礎物理常識再閱讀本篇會較為容易
一、剛體(Rigidbody)組件參數(shù)
剛體組件有兩種,分別是 Rigidbody 組件和 Rigidbody2D 組件,本篇只談前一種剛體組件。
在 Unity 中,若想要一個物體具有在現(xiàn)實世界中的物理效果,比如受重力影響,就要為其添加 Rigidbody 組件,該組件是讓物體產(chǎn)生物理行為的組件。通過剛體組件可以給物體添加一些常見的物理屬性,如質量、摩擦力、碰撞參數(shù)等。
在物理學中,剛體是一個理想模型,通常把在外力作用下,物體的形狀和大小保持不變,而且內(nèi)部各部分相對位置保持恒定的理想模型稱為剛體。
按下物體對象的 Inspector 面板的 Add Component 按鈕,搜索 Rigidbody 即可添加該組件。(或通過 Physics->Rigidbody 分類)
1.Mass 質量
設置物體的質量,默認質量是 1 千克(KG),這時根據(jù)物理學原理來講,只需要給這個物體一個向上的力(9.8N),就可以抵消重力,稍微大于 9.8N,便可以上升。
2.Drag 阻力
設置物體的阻力,默認為 0,則沒有阻力。阻力的方向與物理運動方向相反,該參數(shù)數(shù)值越大,所受到的阻力也就越大,速度的衰減也就越快。極大時物體將會立即停止運動。
3.Angular Drag 角阻力
設置物體的角阻力(旋轉阻力),與該物體的旋轉方向相反,默認為 0.05。設置該值后,物體在任何方向上的旋轉運動都將受到影響。若設置為 0,則物體一旦開始旋轉就不會停止(無重力狀態(tài)下)。該值越大,旋轉衰減越快。
該例子中,下面的物理沒有勾選使用重力選項,用以模擬無重力,當該物體收到外力影響,若沒有角阻力的影響,則會不停旋轉,若沒有阻力的影響,則該物體會不斷移動。
4.Use Gravity 使用重力
設置該物體是否受重力影響,模擬現(xiàn)實世界中自由落體運動。勾選則受到影響,不勾選則模擬無重力環(huán)境下的運動狀態(tài)。
底下三個物體沒有勾選此項,若你看到這里了,別光看著,自己動手玩玩,還挺好玩的。
5. Is Kinematic 是否遵循動力學
設置該物體是否受動力學模擬,勾選則表示該物體不受重力、速度、阻力、質量等物理模擬的影響,只受腳本和動畫的影響而運動。這個有什么用呢,比如當你首先勾選肯定能降低性能消耗,物理系統(tǒng)已經(jīng)不會計算它了,其次它雖然不受物理模擬的影響,但是它依舊是可以影響其他物體的,比如移動通過腳本移動它的 transform,依舊可以撞擊其他剛體!注意僅影響到剛體!
如圖所示,圖中的兩個障礙物僅添加了碰撞體,而沒有勾選此選項的剛體會受到碰撞體的影響,勾選之后則不會受到碰撞體的影響,但是依舊能影響且推動同樣有著剛體組件的物體。至于用途,就要讀者自行發(fā)揮想象了,游戲就是想象!
移動的物體是使用腳本驅動的,不受物理世界影響的:代碼如下。很簡單的一句
public float speed = 3;
void Update()
{
transform.position += new Vector3(0, 0, Time.deltaTime * speed * -1);
}
6.Interpolate 插值
該參數(shù)用于解決Unity中物理模擬和畫面渲染不同步的問題,當不進行插值處理時,計算得到的物理數(shù)據(jù)是上一個物理模擬時間點的數(shù)據(jù),而插值則是獲取最近似當前渲染時間點數(shù)據(jù)的一種手段。當你發(fā)現(xiàn)剛體移動時會發(fā)生抖動,建議調(diào)整一下此選項。
一共兩個參數(shù)
- Interpolate:根據(jù)前一幀來平滑變換
- Extrapolate:根據(jù)下一幀來平滑變換
7.Collision Detection 碰撞檢測
該屬性用于控制避免高速運動的物體穿過其他對象而沒有發(fā)生碰撞。
- Discrete 離散碰撞檢測(默認,適用于大部分剛體,這個肯定是最省資源的,毫無疑問,一般情況下默認這個,不要改)
- Continuous 連續(xù)碰撞檢測(適用于被高速撞擊的物體)
- Continuous Dynamic 連續(xù)動態(tài)碰撞檢測(適用于高速移動的物體)
- Continuous Speculative 連續(xù)掃描碰撞檢測(emmm,不知道,資料好難找)
給大家舉個例子,就明白了![]()
第一個的碰撞檢測是默認的離散檢測,物體直接掉下去了,第二個則是連續(xù)動態(tài)檢測,成功攔住了,這方面資料較少,個人沒這個能力就不往深處講了。
8.Constraints 約束條件
約束物體在某一個方向上的運動和旋轉,默認不約束,各軸的運動旋轉受物理系統(tǒng)控制。這個應該很好理解,舉個例子。
這里我凍結了這扇門的 XYZ 軸的運動和 XZ 軸的旋轉,現(xiàn)在使用物體推門,一個簡單的門就做好了。若想要單扇門的推動效果(不過這里用 Joints 物理關節(jié)更簡單,以后我會寫相關的文章的),讀者自行拓展吧。
二、基本碰撞體(Collider)組件參數(shù)
當一個物理添加了碰撞體組件后,它會默認阻擋剛體的運動,如上述例子中,我添加了一塊 Plane,它就會默認阻擋受重力影響的剛體的下墜。這是因為當我創(chuàng)建它的時候它就自帶了一個碰撞體組件。
碰撞體組件定義了物體的物理形狀,且碰撞體本身是隱形的,大家可以想想空氣墻的例子。
當你創(chuàng)建了一個 Cube,該物體就自帶了一個 Box Collider。最簡單且最節(jié)省計算資源的碰撞體就是一系列基本碰撞體。當你右鍵創(chuàng)建一系列基本模型時,它們就自帶了一系列基本碰撞體。
一個物體可以帶有多個碰撞體組件,這樣就形成了組合碰撞體。
1.基本參數(shù)
基本碰撞體組件的參數(shù)如下,Edit Collider用于編輯碰撞體大小,Center和Size用于指定中心和范圍,就不多說了,下面重點說說Is Trigger屬性和Material屬性
2. Is Trigger
前面說過,碰撞體會默認阻擋剛體的運動,但是有些時候需要檢測兩個物體發(fā)生重疊但又不想引起物理上的碰撞,就需要勾選此選項,將碰撞體變成一個觸發(fā)器。
當勾選此項后,該物體就不會再阻擋剛體運動了,但當有剛體與當前物體發(fā)生重疊的時候,會調(diào)用 OnTriggerEnter()方法。
這里我給底下的平面加了觸發(fā)函數(shù)的腳本,然后將其碰撞體設置成了觸發(fā)器。也就是勾選了 Is Trigger
private void OnTriggerEnter(Collider other) {
Debug.Log("檢測到物體【" + other.name + "】與當前碰撞體發(fā)生重疊!");
}
3.Material 物理材質
這個選項用于模擬物體表面的物理材質,對于地面而言,比如冰面、木板、水泥板這些。對于物體本身而言,比如物理自身的彈性,物理自身的平滑度之類的,都會直接影響到物理模擬的效果。
創(chuàng)建物理材質和創(chuàng)建普通材質的方法是一樣的,右鍵菜單里面找到 Physic Material,物理材質參數(shù)如圖所示
- Dynamic Friction 運動摩擦力
- 取值范圍 0~1
- Static Friction 靜止摩擦力
- 取值范圍 0~1
- Bounciness 表面彈性
- 取值范圍 0~1,值為 0 時無彈性
- Friction Combine 摩擦力混合
- 發(fā)生碰撞的兩個碰撞體對象的摩擦力的混合方式
- Maximum 取最大值
- MuItiply 取相乘值
- Minimum 取最小值
- Average 取平均值
- Bounce Combine 彈性混合
- 發(fā)生碰撞的兩個碰撞體對象的摩擦力的彈性方式
- Maximum 取最大值
- MuItiply 取相乘值
- Minimum 取最小值
- Average 取平均值
來舉個例子,比如模擬冰塊在冰面上
我同時給三個碰撞體和 Plane 都給了如下參數(shù)的物理材質,同時給 Plane 加了一點傾斜角度
三、碰撞體的分類
碰撞體因為是否具有剛體組件以及剛體組件上是否設置動力學剛體等,都會導致具有該組件的物體的物理碰撞特性發(fā)生變化,所以根據(jù)以上不同之處,將碰撞體分為三類:靜態(tài)碰撞體、剛體碰撞體、動力學剛體碰撞體。
1.靜態(tài)碰撞體(Static Collider)
沒有掛載剛體組件的碰撞體叫做靜態(tài)碰撞體。
常用于制作游戲中的固定部分,比如地形,障礙物,樹木等,因為這些部分一般沒有移動的需求,剛體撞擊的時候,位置也不會變化,比如大名鼎鼎的 GTA5 里面,樹木就是無敵的。
對于有移動碰撞體的需求,建議使用剛體碰撞體或動力學剛體碰撞體。請不要使用此種方式,否則會增大物理系統(tǒng)的計算量。
2.剛體碰撞體(Rigidbody Collider)
掛載了剛體組件的碰撞體叫做剛體碰撞體。
物理引擎會一直計算該碰撞體的物理狀態(tài)。
3.動力學剛體碰撞體(Kinematic Rigidbody Collider)
掛載了剛體組件且剛體組件設置為動力學剛體的碰撞體叫做動力學剛體碰撞體。(好繞)
常用于制作如門,固定軌跡移動的關卡道具等。
四、剛體的休眠
上面關于碰撞體的分類中說過,剛體碰撞體會被物理引擎一直計算物理狀態(tài)。但是!這樣會不會太耗費資源了呢?Unity 中怎么解決的呢,這就引入了一個概念,剛體的休眠。
當一個剛體的移動速度和旋轉已經(jīng)慢于某個事先定義的閾值了(一般很小很小,可修改),并且保持了一定的時間,那是否可以說,這個剛體短時間內(nèi)已經(jīng)相對靜止了,這時就可以說該物體進入了“休眠”狀態(tài),休眠狀態(tài)中的剛體會被物理系統(tǒng)視而不見,所以自然就節(jié)約了運算資源,直到它被重新“喚醒”為止,也就是移動速度和旋轉高于預定值了,開始運動了。
請注意,剛體的休眠完全是自動發(fā)生的,喚醒剛體自然也是自動發(fā)生的。
在 Rigidbody 組件中,帶有 sleepVelocity 和 sleepAngularVelocity 屬性,Unity 就是通過這兩個屬性來判定剛體是否需要進入休眠狀態(tài)的。但需要特別注意的是!Unity 目前已經(jīng)棄用這兩個屬性,轉而使用 sleepThreshold,根據(jù)官方 API 的描述,“該屬性經(jīng)過質量標準化的能量閾值,當?shù)陀谠撻撝禃r,對象開始進入休眠狀態(tài)”。說人話,就是將上述兩個屬性通過一些算法合二為一了,只需要判斷 sleepThreshold 是否低于預設的閾值就可以判斷該剛體是否休眠了。該閾值一般為 0.005,可通過,[Edit]->[Project Settings]->[Physics]來設置,如下圖所示。
在 Rigidbody 組件中,你也可以通過 IsSleeping()函數(shù)來判斷剛體是否正在休眠。但是該函數(shù)的本質還是判斷 sleepThreshold。
當剛體進入休眠狀態(tài),是無法和碰撞體發(fā)生碰撞的,因為剛體進入休眠狀態(tài),其物理系統(tǒng)就已經(jīng)不再計算了,自然也無法產(chǎn)生碰撞信息和觸發(fā)碰撞事件。
你也可以 WakeUp()來強制喚醒一個剛體。
下圖這個例子中演示了剛體休眠時,則剛體不會對碰撞體產(chǎn)生碰撞
大正方體帶有剛體組件,其他僅有碰撞體,當大正方體下落時,受物理系統(tǒng)重力影響,自由下落,與其他碰撞體發(fā)生碰撞,當落下靜止時,剛體立刻休眠,這時拖動底下的碰撞體,則直接穿過,這時剛體處于懸空狀態(tài),被物理系統(tǒng)喚醒,又受到重力影響,開始下落,又與地面發(fā)生碰撞,立刻休眠。
public Rigidbody rig;
public bool IsSleeping;
void FixedUpdate()
{
IsSleeping = rig.IsSleeping();
}
五、剛體和碰撞體的碰撞測試及觸發(fā)方法
寫到這,基本可以畫上句號了,但是這里還是單開一小節(jié),列舉一下剛體和碰撞體之間,到底需要滿足何種條件才會發(fā)生碰撞呢?需要滿足何種條件才會觸發(fā)事件呢?
首先必須兩個都是碰撞體,且運動一方為非運動學剛體,才可以發(fā)生碰撞!碰撞時會產(chǎn)生碰撞事件,OnCollision()
其次,一方碰撞體必須勾選 Is Trigger 才會觸發(fā) OnTrigger()事件
1.什么時候才會發(fā)生碰撞
第三小節(jié)我們說過關于碰撞體的分類,一共分為三類靜態(tài)碰撞體、剛體碰撞體、運動學剛體碰撞體,我們把它兩兩組合,下面簡要羅列一下可能出現(xiàn)的情況,一共 9 種情況。
這里如果看不明白,建議再去第三小節(jié)反復觀看!
注意:當發(fā)生碰撞,雙方都會觸發(fā) OnCollision()事件,當不發(fā)生碰撞,則雙方都不會觸發(fā)事件。
2.什么時候才會觸發(fā) OnTrigger
這里請回到第二小節(jié)看看關于碰撞體變成觸發(fā)器的說明,明白了請往下看。根據(jù)上文可得,當碰撞體勾選了 Is Trigger 之后才可能觸發(fā) OnTrigger()事件,若不勾選,那只能觸發(fā) OnCollision()事件,這里希望讀者思路清晰,別亂。每看一段,就自己做一次實驗,慢慢來。
下面羅列一下可能觸發(fā) OnTrigger 的情況,一共有…36 種
注意:這里絕對不會出現(xiàn)一個觸發(fā) OnCollision,另一個觸發(fā) OnTrigger 的情況,如果在表格中打勾,這就說明,雙方必定都會觸發(fā) OnTrigger 事件!上一個圖也一樣,若表格打勾,則雙方必定都會觸發(fā) OnCollision 事件!
3.碰撞和觸發(fā)方法
上面你能看懂,這些肯定不成問題,就不廢話了。
觸發(fā)檢測
1.OnTriggerEnter( Collider other )當進入觸發(fā)器
2.OnTriggerExit( Collider other )當退出觸發(fā)器
3.OnTriggerStay( Collider other )當逗留觸發(fā)器
碰撞檢測:
1.OnCollisionEnter( Collision other ) 當進入碰撞器
2.OnCollisionExit( Collision other ) 當退出碰撞器
3.OnCollisionStay( Collision other ) 當逗留碰撞器文章來源:http://www.zghlxwxcb.cn/news/detail-402143.html
六、總結與參考資料
1.總結
- 關于碰撞體組件中還有 Mesh(網(wǎng)格)碰撞體、Wheel(車輪)碰撞體和 Terrain(地形)碰撞體,篇幅有限,這些組件以后詳說。
- 雙方必須都要有碰撞器,且運動的一方必須是非運動學剛體才可以發(fā)生碰撞(N 次強調(diào),這句話很重要!)
- 碰撞體分類:靜態(tài)碰撞體,剛體碰撞體,運動學剛體碰撞體。
- 當剛體進入休眠狀態(tài),無法與碰撞體發(fā)生碰撞
- 勾選Is Trigger可以將碰撞體變?yōu)橛|發(fā)器
2.參考資料
[1]吳亞峰.《Unity3D游戲開發(fā)標準教程》
[2]馬瑤.《Unity 3D腳本編程與游戲開發(fā)》
[3]鄭洪智.Unity剛體詳解
[4]冬菊子.unity3d 理解剛體(Rigidbody)和碰撞體(Collider)以及觸發(fā)器(Is Trigger),邊學邊更新
[5]一白夢人.【Untiy學習筆記】Rigidbody組件及其常用函數(shù)
[6]億洋.Unity 理解剛體(Rigidbody)和碰撞體(Collider)和觸發(fā)器(Is Trigger)以及剛體休眠(Rigidbody Sleeping)
[7]Tonge.Unity3D深入淺出-物理材質(Physics Materials)
[8]只待蒼霞.論Collision Detection的作用
[9]月落烏啼霜月落.【Unity 22】 Unity 力,扭矩,剛體,觸發(fā)器的簡單使用
[10]網(wǎng)絡.解決Unity物體速度過快無法進行碰撞檢測(碰撞檢測穿透)
[11]網(wǎng)絡.Unity圣典和官方API以及部分百度百科文章來源地址http://www.zghlxwxcb.cn/news/detail-402143.html
到了這里,關于詳解Unity中的剛體和碰撞體組件的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!