一、剛體 Rigid Body
? 剛體利用體積(碰撞器 Collider)進行碰撞計算,模擬真實的碰撞效果,產(chǎn)生力的作用
? 碰撞產(chǎn)生的必要條件:
- 兩個物體都有碰撞器 Collider
- 至少一個物體有剛體
-
Mass:質(zhì)量
默認為千克,質(zhì)量越大慣性越大
-
Drag:空氣阻力
根據(jù)力移動對象時影響空氣阻力大小
0 表示沒有空氣阻力
-
Augular Drag:旋轉(zhuǎn)阻力
根據(jù)扭矩旋轉(zhuǎn)對象時影響對象的空氣阻力大小
0 表示沒有阻力
-
Use Gravity:是否受重力影響
-
Is Kinematic:是否設(shè)置為運動學
如果啟用,對象將不會被物理引擎驅(qū)動,只能通過 Transform 對其進行操作
對于移動平臺,或者如果要動畫附加了 HingeJoint 的剛體,此屬性將非常有用
-
Interpolate:插值運算
-
None:不應(yīng)用插值運算
-
Interpolate:根據(jù)前一幀的變換來平滑變換
-
Extrapolate:插值運算
根據(jù)下一幀的估計變換來平滑變換,若物理幀時間過長,此效果將不好
-
-
Collison Detection:碰撞檢測模式
-
Discrete:離散檢測
對場景中的所有其他碰撞體使用離散碰撞檢測,其他碰撞體在測試碰撞時會使用離散檢測。
用于正常碰撞(默認值)
-
Continuous:連續(xù)檢測
對動態(tài)碰撞體(具有剛體)使用離散碰撞檢測
對靜態(tài)碰撞體(沒有剛體)使用連續(xù)碰撞檢測
設(shè)置為連續(xù)動態(tài)的剛體,將在測試與該剛體的碰撞時使用連續(xù)碰撞檢測(物理性能消耗較大,物體運動緩慢時請設(shè)置為 Discrete)
其他剛體將使用離散碰撞檢測
-
Continuous Dynamic:連續(xù)動態(tài)檢測
對設(shè)置為連續(xù)和連續(xù)動態(tài)碰撞的對象使用連續(xù)碰撞檢測
對靜態(tài)碰撞體(沒有剛體)使用連續(xù)碰撞檢測
對其他碰撞體使用離散碰撞檢測
用于快速移動的對象
-
Continuous Speculative:連續(xù)推測檢測
對剛體和碰撞體使用推測性連續(xù)碰撞檢測
通常比連續(xù)碰撞檢測的成本更低
無剛體碰撞盒 Discrete Continuous Continuous Dynamic Continuous Speculative 無剛體碰撞盒 不檢測碰撞 Discrete Continuous Continuous Continuous Speculative Discrete Discrete Discrete Discrete Discrete Continuous Speculative Continuous Continuous Discrete Discrete Continuous Continuous Speculative Continuous Dynamic Continuous Discrete Continuous Continuous Continuous Speculative Continuous Speculative Continuous Speculative Continuous Speculative Continuous Speculative Continuous Speculative Continuous Speculative 性能消耗關(guān)系:Continuous Dynamic > Continuous Speculative > Continuous > Discrete
-
-
Constrains:對剛體運動的約束
- Freeze Position:限制剛體在世界坐標軸下 X、Y、Z 軸的移動
- Freeze Rotation:限制剛體在世界坐標軸下 X、Y、Z 軸的旋轉(zhuǎn)
-
Info:用于顯示參數(shù)的面板,不修改里面的值
二、碰撞器 Collider
? 碰撞器表示物體的體積(形狀)
? 碰撞器種類一共有 6 種:
- 盒狀碰撞器 Box Collider
- 球狀碰撞器 Sphere Collider
- 膠囊碰撞器 Capsule Collider
- 網(wǎng)格碰撞器 Mesh Collider
- 輪胎碰撞器 Wheel Collider
- 地形碰撞器 Terrain Collider
? 常用的為前 3 種
(一)共同參數(shù)
-
Edit Collider:編輯碰撞器的大小
-
Is Trigger:是否為觸發(fā)器
如果啟用,則該碰撞體用于觸發(fā)事件,并被物理引擎所忽略
主要用于進行沒有物理效果的碰撞檢測
-
Material:物理材質(zhì)
可以確定碰撞體和其他對象碰撞時的交互(表現(xiàn))方式
-
Center:碰撞體的中心偏移位置
(二)常用碰撞器
- Box Collider
- Size:碰撞體在 X、Y、Z 方向上的大小
- Sphere Collider
- Radius:球形碰撞體的半徑大小
- Capsule Collider
- Radius:膠囊體的半徑
- Height:膠囊體的高度
- Direction:膠囊體在對象局部空間中的軸向
(三)異形物體使用多種碰撞器組合
? 剛體對象的子對象碰撞信息參與碰撞檢測
? 即父物體添加 Rigid Body,子物體設(shè)置 Collider。
(四)不常用碰撞器
-
Mesh Collider
-
Convex:是否為凸面的
勾選后,該 Mesh Collider 將會與其他 Mesh Collider 發(fā)生碰撞,最多支持 255 個三角面片
如果該對象添加了剛體 Rigid Body,則該選項必須勾選,否則會報錯
-
Cooking Options:物理引擎對網(wǎng)格的處理方式
不常用
-
Mesh:引用需要用于碰撞的網(wǎng)格
-
-
Wheel Collider
賽車游戲中使用,其他時候不常用
注意:添加 Wheel Collider 后一定要添加 Rigid Body(或在父物體添加),否則將失效
-
Terrain Collider
地形系統(tǒng)中使用
性能較為低下,很少使用
三、物理材質(zhì)
? 在 Project 中創(chuàng)建物理材質(zhì) Physics Material
-
Dynamic Friction:滑動摩擦力
0 表示絕對光滑,1 表示迅速靜止
-
Static Frction:靜摩擦力
0 表示絕對光滑,1 表示無法移動
-
Bounciness:表面彈性
0 表示不會反彈,1 表示反彈沒有能量損失,甚至可能會增加少量能量
-
Friction Combine:摩擦力組合方式
- Average:取平均值
- Minimum:取最小值
- Maximum:取最大值
- Multiply:相乘
-
Bounce Combine:彈性組合方式
- Average:取平均值
- Minimum:取最小值
- Maximum:取最大值
- Multiply:相乘
四、碰撞檢測函數(shù)
? 碰撞和觸發(fā)響應(yīng)函數(shù)屬于特殊的生命周期函數(shù),也是通過反射調(diào)用
? 碰撞和觸發(fā)器函數(shù)都可以寫成虛函數(shù),在子類去重寫邏輯
(一)物理碰撞檢測響應(yīng)函數(shù)
// 碰撞觸發(fā)接觸時會 自動執(zhí)行這個函數(shù)
private void OnCollisionEnter(Collision collision)
{
// Collision類型的 參數(shù) 包含了 碰到自己的對象的相關(guān)信息
// 關(guān)鍵參數(shù)
// 1.碰撞到的對象碰撞器的信息
collision.collider
// 2.碰撞對象的依附對象(GameObject)
collision.gameObject
// 3.碰撞對象的依附對象的位置信息
collision.transform
// 4.觸碰點數(shù)相關(guān)
collision.contactCount
// 接觸點 具體的坐標
ContactPoint[] pos = collision.contacts;
// 只要得到了 碰撞到的對象的 任意一個信息 就可以得到它的所有信息
print(this.name + "被" + collision.gameObject.name + "撞到了");
}
// 碰撞結(jié)束分離時 會自動執(zhí)行的函數(shù)
private void OnCollisionExit(Collision collision)
{
print(this.name + "被" + collision.gameObject.name + "結(jié)束碰撞了");
}
// 兩個物體相互接觸摩擦時 會不停的調(diào)用該函數(shù)
private void OnCollisionStay(Collision collision)
{
print(this.name + "一直在和" + collision.gameObject.name + "接觸");
}
(二)觸發(fā)器檢測響應(yīng)函數(shù)
// 觸發(fā)開始的函數(shù) 當?shù)谝淮谓佑|時 會自動調(diào)用
protected virtual void OnTriggerEnter(Collider other)
{
print(this.name + "被" + other.gameObject.name + "觸發(fā)了");
}
// 觸發(fā)結(jié)束的函數(shù) 當水乳相融的狀態(tài)結(jié)束時 會調(diào)用一次
private void OnTriggerExit(Collider other)
{
print(this.name + "被" + other.gameObject.name + "結(jié)束水乳相融的狀態(tài)了");
}
// 當兩個對象 水乳相融的時候 會不停調(diào)用
private void OnTriggerStay(Collider other)
{
print(this.name + "和" + other.gameObject.name + "正在水乳相融");
}
-
只要掛載的對象能和別的物體產(chǎn)生碰撞或者觸發(fā),那么對應(yīng)的這 6 個函數(shù)就能夠被響應(yīng)
-
6 個函數(shù)不是說都得寫,一般根據(jù)需求來進行選擇書寫,一般用 Enter 函數(shù)較多
-
如果是一個異形物體,剛體在父對象上,如果你想通過子對象上掛腳本檢測碰撞是不行的,必須掛載到這個剛體父對象上才行
五、剛體加力
(一)剛體自帶添加力的方法
- 獲取剛體組件
rigidBody = this.GetComponent<Rigidbody>();
- 1
- 添加力
// 相對世界坐標
// 世界坐標系 Z軸正方向加了一個力
// 加力過后 對象是否停止移動 是由阻力決定的
// 如果阻力為0 那給了一個力過后 始終 是不會停止運動
rigidBody.AddForce(Vector3.forward * 10);
// 如果想要在 世界坐標系方法中 讓對象 相對于自己的面朝向動
rigidBody.AddForce(this.transform.forward * 10);
// 相對本地坐標
rigidBody.AddRelativeForce(Vector3.forward * 10);
//如果你希望即使有阻力 也希望對象一直動 那你就把下面代碼放在Update函數(shù)中 一直“推”就行了
rigidBody.AddForce(Vector3.forward * 10);
- 添加扭矩力
// 相對世界坐標
// 繞y軸旋轉(zhuǎn)
rigidBody.AddTorque(Vector3.up * 10);
// 相對本地坐標
rigidBody.AddRelativeTorque(Vector3.up * 10);
- 直接改變速度
// 這個速度方向 是相對于 世界坐標系的
// 如果要直接通過改變速度 來讓其移動 一定要注意這一點
rigidBody.velocity = Vector3.forward * 5;
- 模擬爆炸效果
// 模擬爆炸的力 一定是 所有希望產(chǎn)生爆炸效果影響的對象
// 都需要得到他們的剛體 來執(zhí)行這個方法 才能都有效果
// 參數(shù)一 爆炸力
// 參數(shù)二 爆炸位置
// 參數(shù)三 爆炸半徑范圍
rigidBody.AddExplosionForce(100, Vector3.zero, 10);
(二)力的模式
// 第二個參數(shù) 力的模式 主要的作用 就是 計算方式不同而已
// 由于4中計算方式的不同 最終的移動速度就會不同
rigidBody.AddForce(Vector3.forward * 10, ForceMode.Acceleration);
? 速度計算公式:v = F * t / m(動量定理)
-
Acceleration
給物體增加一個持續(xù)的加速度,忽略其質(zhì)量
F = (0, 0, 10)、t = 0.02 s、m = 默認為 1
v = 10 * 0.02 / 1 = 0.2 m/s
每物理幀移動 0.2 m/s * 0.02 = 0.004 m -
Force
給物體添加一個持續(xù)的力,與物體的質(zhì)量有關(guān)
F = (0, 0, 10)、t = 0.02 s、m = 2 kg
v = 10 * 0.02 / 2 = 0.1 m/s
每物理幀移動 0.1 m/s * 0.02 = 0.002 m -
Impulse
給物體添加一個瞬間的力,與物體的質(zhì)量有關(guān),忽略時間,t 默認為1
F = (0, 0, 10)、t = 1 s、m = 2 kg
v = 10 * 1 / 2 = 5 m/s
每物理幀移動 5 m/s * 0.02 = 0.1 m -
VelocityChange
給物體添加一個瞬時速度,忽略質(zhì)量,忽略時間
F = (0, 0, 10)、t = 1 s、m = 默認為 1
v = 10 * 1 / 1 = 10 m/s
每物理幀移動 10 m/s * 0.02 = 0.2 m
(三)力場
? 為物體添加 Constant Force,若物體之前沒有 Rigid Body,則會為其自動添加
? 進行參數(shù)設(shè)置
(四)剛體休眠
? Unity 為了節(jié)約性能,為剛體添加了休眠機制:
Rigidbody sleeping happens completely automatically. Whenever a rigidbody is slower than the sleepAngularVelocity and sleepVelocity it will start falling asleep. After a few frames of resting it will then be set to sleep. When the body is sleeping, no collision detection or simulation will be performed anymore. This saves a lot of CPU cycles.
剛體休眠完全自動發(fā)生。只要剛體的速度低于 sleepAngularVelocity 和 sleepVelocity,該剛體就會開始休眠。其空閑一些幀后,就會被設(shè)置成休眠狀態(tài)。處于休眠狀態(tài)中的物體,不會再對其進行碰撞檢測和模擬。這會節(jié)約大量的 CPU 開銷。
? 例如,在為 Cube 添加 Rigid Body 后其下落靜止在平面上
? 將平面旋轉(zhuǎn)一定角度后,發(fā)現(xiàn) Cube 懸空,說明此時 Cube 的剛體休眠了
? 將平面向下以一定速度拖動,則 Cube 下落,剛體被激活
文章來源:http://www.zghlxwxcb.cn/news/detail-486674.html
? 使用代碼控制:文章來源地址http://www.zghlxwxcb.cn/news/detail-486674.html
// 獲取剛體是否處于休眠狀態(tài) 如果是
if (rigidBody.IsSleeping())
{
// 就喚醒它
rigidBody.WakeUp();
}
到了這里,關(guān)于Unity入門7——物理系統(tǒng)之碰撞檢測的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!