轉載:Unity3d 汽車物理引擎 WheelCollider總結
WheelCollider總結
寫了前面兩篇文章,我想總結一下WheelCollider!
讓我們能夠更清晰的學會物理車的開發!
1.車的層次結構
一般這樣分,車身,車身的包圍盒,四個輪子和四個輪子的碰撞器!
2.分析驅動車的原理
車主體本身加了一個Rigidbody,物理車我們可以加一個到兩個包圍盒來
包住車身(但是絕對不能包住車輪,否則物理車不運動!)物理車有前后四個輪子,那么有的車需要前輪進行驅動,后輪進 行輔助,有的車需要后輪進行驅動,前輪進行輔助!這個很好辦,如果是哪個
輪進行驅動,就設置這個輪子的WheelCollider.motorTorque,也就是輪子
的動力,WheelCollider.steerAngle,設置輪子的旋轉角度,這樣就基本OK
了,那么車輪如何隨着地面的起伏行走呢?這就是另一個問題了!
關於如何使車輪始終保持在地面之上,並且隨着地面的起伏進行起伏的運 動?
可以從車輪碰撞器(WheelCollider)向地面發射一條射線,用Physics.Raycast來獲取一個RaycastHit;獲取碰撞點,調整車輪的位置,
這里對WheelCollider的屬性做一個補充,是拷貝的http://game.ceeger.com/Components/class-WheelCollider.html的片段!
Properties 屬性
-
Center 中心Center of the wheel in object local space. 車輪在對象自身坐標的中心位置
-
Radius 半徑Radius of the wheel. 車輪的半徑大小
-
Suspension Distance 懸掛距離Maximum extension distance of wheel suspension, measured in local space. Suspension always extends downwards through the local Y-axis. 最大車輪懸掛伸縮距離,以自身坐標計算。懸掛總是通過自身Y軸伸展向下。
-
Suspension Spring 懸掛彈簧The suspension attempts to reach a Target Position by adding spring and damping forces. 通過添加彈簧和阻尼力,懸掛試圖達到目標位置(Target Position)。
-
Spring 彈簧Spring force attempts to reach the Target Position. A larger value makes the suspension reach the Target Position faster. 彈簧力嘗試達到目標位置(Target Position),大的值可使懸掛快速達到目標位置(Target Position)。
-
Damper 阻尼器Dampens the suspension velocity. A larger value makes the Suspension Spring move slower. 阻尼器控制懸掛速度,大的值可使懸掛彈簧移動變慢。
-
Target Position 目標位置The suspension's rest distance along Suspension Distance. 0 maps to fully extended suspension, and 1 maps to fully compressed suspension. Default value is zero, which matches the behavior of a regular car's suspension. 懸掛的靜止狀態距離沿着懸掛距離,0值充分伸展懸掛,1值充分壓縮懸掛,默認值為0,這是一個標准的汽車懸掛行為
-
Mass 質量The Mass of the wheel. 車輪的質量
-
Forward/Sideways Friction 向前摩擦力Properties of tire friction when the wheel is rolling forward and sideways. See Wheel Friction Curves section below. 當車輪向前/側向滾動時的摩擦力屬性。參見下面車輪摩擦力曲線部分。
對於物理車就寫到這兒,以后理解的更深一些,就繼續續寫……
下面我就物理,Rigidbody,以及“關節”的分別做個教程,呵呵……!
Unity3d物理汽車第二篇
1.第一篇留下的問題,還沒有得到解答!我目前的結論就是可以賦值為負值!
2.我自己用了個方塊做為車身,然后用四個輪子,把代碼套了上去,車子竟然一動不動!
並且出現了以下警告:
MissingComponentException: There is no 'AudioSource' attached to the "Cube" game object, but a script is trying to access it.
You probably need to add a AudioSource to the game object "Cube". Or your script needs to check if the component is attached before using it.
PlayerCar_Script.Update () (at Assets/Scripts/Car Control/PlayerCar_Script.js:48)
我貼出來48行的代碼:
audio.pitch = Mathf.Abs(EngineRPM / MaxEngineRPM) + 1.0 ;
就是audio,但是我忘了給物理車添加Audio Source(音頻源),導致程序出現警告,導致后面的程序沒有執行!
所以,汽車就沒有開動了!當大家遇到警告的提示之后,一定要分析原因,檢查問題!養成良好的分析問題的習慣,這就是積累經驗的時候了!
Audio Source中一個參數pitch是音頻源的音調!這里的audio.pitch的最大值是2;
3.現在貼出來車輪與地面碰撞的代碼!JS語言寫的!
//車輪碰撞器
var CorrespondingCollider : WheelCollider;
//車輪印
var SlipPrefab : GameObject;
//車輪的旋轉值
private var RotationValue : float = 0.0;
//更新函數
function Update () {
//光線投射碰撞,用來獲取從raycast函數中得到的信息反饋的結構。
var hit : RaycastHit;
//WheelCollider是掛在一個空物體上的Transform上,所以,要用空物體的變換去變換
WheelCollider的中心點(本地坐標的點),這樣ColliderCenterPoint就是世界坐標中的點了!
var ColliderCenterPoint : Vector3 = CorrespondingCollider.transform.TransformPoint( CorrespondingCollider.center );
//最主要的部分
//光線投射,從ColliderCenterPoint的位置,向CollesponndingCollider.transform.down方向,發射一條長度為 (車輪懸掛的最大延長距離(suspensionDistance)+車輪碰撞器的半徑(radius))的線段!准確的叫線段!返回hit這個信息
if ( Physics.Raycast( ColliderCenterPoint, -CorrespondingCollider.transform.up, hit, CorrespondingCollider.suspensionDistance + CorrespondingCollider.radius ) )
{
//如果這條線段碰撞到了物體!
//設置車輪物體(不是車輪碰撞器)的坐標為碰撞點的坐標+車輪碰撞器的半徑
transform.position = hit.point + (CorrespondingCollider.transform.up * CorrespondingCollider.radius);
}else{
//如果沒有碰撞,就讓車輪物體,不斷下落,每幀下落(車輪懸掛的最大延長距離(suspensionDistance))的 距離
transform.position = ColliderCenterPoint - (CorrespondingCollider.transform.up * CorrespondingCollider.suspensionDistance);
}
}
//車輪物體的旋轉為 車輪碰撞器所附加的空物體的變換*車輪碰撞器繞x旋轉RotationValue,
//繞Y軸旋轉steerAngle,繞Z軸旋轉0度
WheelCollider.steerAngel返回車輪碰撞器繞自身Y軸旋轉的角度
//乘法的順序很重要,這里的意思,實際中是先后面的旋轉,再前面的旋轉!
transform.rotation = CorrespondingCollider.transform.rotation * Quaternion.Euler( RotationValue, CorrespondingCollider.steerAngle, 0 );
// 累加RatationValue 每一幀車輪的旋轉值為rpm*6*Time.deltaTime
RotationValue += CorrespondingCollider.rpm * ( 360/60 ) * Time.deltaTime;
//WheelHit是有WheelCollider返回的碰撞信息
var CorrespondingGroundHit : WheelHit;
//返回WheelHit
CorrespondingCollider.GetGroundHit( CorrespondingGroundHit );
//WheelCollider.sidewaySlip是側輪滑動的值,如果這個值大於2.0,則復制一個粒子對象,做為車輪印!
if ( Mathf.Abs( CorrespondingGroundHit.sidewaysSlip ) > 2.0 ) {
if ( SlipPrefab ) {
//復制 , SlipPrefab原物體,WheelCollider.point車輪其它物體碰撞點的位置,Quaternion.identity,不進行任何旋轉
Instantiate( SlipPrefab, CorrespondingGroundHit.point, Quaternion.identity );
}
}
我有理解不正確的地方,麻煩指正一下……!
下一篇總結一下,呵呵!