# [Mark] Unity3d之 汽车物理系统

这里，就写个物理车的！

首先，资料的来源!http://unity.gopedu.com/在这个链接的底部有下载的链接，如果下载不 到，   我可以共享出来！

第二部，开始一些翻译和讲解！

1.物理车的碰撞！

其中草绿色线条是车的两个包围盒！四个轮子加了四个车轮碰撞器(WheelCollider);

2.物理车的层次结构关系

根节点是PlayerCar,Colliders,就是第一张图中的两个包围盒

WheelColliders的子物体就是四个车轮碰撞器！

Wheels的子物体就是四个车轮！

第三部份，代码注解：

代码使用JS写的！

首先是：PlayerCar_Script.js

1. // ----------- CAR TUTORIAL SAMPLE PROJECT, ? Andrew Gotow 2009 -----------------

2. // Here's the basic car script described in my tutorial at [url]www.gotow.net/andrew/blog.[/url]
3. // A Complete explaination of how this script works can be found at the link above, along
4. // with detailed instructions on how to write one of your own, and tips on what values to
5. // assign to the script variables for it to work well for your application.

7. //这些是外国人写的赛车例子，我个人认为非常好，是用JS写的！
8. //我来注解一下！
9. // These variables allow the script to power the wheels of the car.
10. //前左轮和前右轮
11. var FrontLeftWheel : WheelCollider;
12. var FrontRightWheel : WheelCollider;
13. // These variables are for the gears, the array is the list of ratios. The script
14. // uses the defined gear ratios to determine how much torque to apply to the wheels.
15. //齿轮转数系数
16. var GearRatio : float[];
17. //档位
18. var CurrentGear : int = 0;
19. // These variables are just for applying torque to the wheels and shifting gears.
20. // using the defined Max and Min Engine RPM, the script can determine what gear the
21. // car needs to be in.
22. //向前的动力
23. var EngineTorque : float = 600.0;
24. //引擎最大的转速
25. var MaxEngineRPM : float = 3000.0;
26. //引擎最小的转速
27. var MinEngineRPM : float = 1000.0;
28. private var EngineRPM : float = 0.0;
29. function Start () {
30.     // I usually alter the center of mass to make the car more stable. I'ts less likely to flip this way.
31.     //设置车的中心点，一般在车的底盘下，这样车行驶起来稳定，不会轻易翻车！
32.     rigidbody.centerOfMass.y = -1.5;
33. }
34. function Update () {
35.     // This is to limith the maximum speed of the car, adjusting the drag probably isn't the best way of doing it,
36.     // but it's easy, and it doesn't interfere with the physics processing.
37.     //设置车的阻力为 车的向前的速度的长度除以250
38.     rigidbody.drag = rigidbody.velocity.magnitude / 250;
39.     // Compute the engine RPM based on the average RPM of the two wheels, then call the shift gear function
40.     //档位的转速值车
41.     EngineRPM = (FrontLeftWheel.rpm + FrontRightWheel.rpm)/2 * GearRatio[CurrentGear];
42.     ShiftGears();
43.     // set the audio pitch to the percentage of RPM to the maximum RPM plus one, this makes the sound play
44.     // up to twice it's pitch, where it will suddenly drop when it switches gears.
45.     //音频源的音调 发动机的引擎转速越快，则音调越高！
46.     audio.pitch = Mathf.Abs(EngineRPM / MaxEngineRPM) + 1.0 ;
47.     // this line is just to ensure that the pitch does not reach a value higher than is desired.
48.     //超过2.0则归位到2.0
49.     if ( audio.pitch > 2.0 ) {
50.         audio.pitch = 2.0;
51.     }
52.     // finally, apply the values to the wheels.    The torque applied is divided by the current gear, and
53.     // multiplied by the user input variable.
54.     //前面的两个轮子的力矩
55.     FrontLeftWheel.motorTorque = EngineTorque / GearRatio[CurrentGear] * Input.GetAxis("Vertical");
56.     FrontRightWheel.motorTorque = EngineTorque / GearRatio[CurrentGear] * Input.GetAxis("Vertical");
57.     Debug.Log(Input.GetAxis("Vertical"));
58.     // the steer angle is an arbitrary value multiplied by the user input.
59.     FrontLeftWheel.steerAngle = 10 * Input.GetAxis("Horizontal");
60.     FrontRightWheel.steerAngle = 10 * Input.GetAxis("Horizontal");
61. }
62. //换档位
63. function ShiftGears() {
64.     // this funciton shifts the gears of the vehcile, it loops through all the gears, checking which will make
65.     // the engine RPM fall within the desired range. The gear is then set to this "appropriate" value.
66.     //如果当前引擎的值大于最大引擎
67.     if ( EngineRPM >= MaxEngineRPM ) {
68.         var AppropriateGear : int = CurrentGear;
69.         //则从0开始，往上查，如果左轮的rpm乘以齿轮数小于
70.         for ( var i = 0; i < GearRatio.length; i ++ ) {
71.             if ( FrontLeftWheel.rpm * GearRatio[i] < MaxEngineRPM ) {
72.                 AppropriateGear = i;
73.                 break;
74.             }
75.         }
76.
77.         CurrentGear = AppropriateGear;
78.     }
79.
80.     if ( EngineRPM <= MinEngineRPM ) {
81.         AppropriateGear = CurrentGear;
82.
83.         for ( var j = GearRatio.length-1; j >= 0; j -- ) {
84.             if ( FrontLeftWheel.rpm * GearRatio[j] > MinEngineRPM ) {
85.                 AppropriateGear = j;
86.                 break;
87.             }
88.         }
89.
90.         CurrentGear = AppropriateGear;
91.     }
92. }

FrontLeftWheel.motorTorque = EngineTorque / GearRatio[CurrentGear] * Input.GetAxis("Vertical");

FrontRightWheel.motorTorque = EngineTorque / GearRatio[CurrentGear] * Input.GetAxis("Vertical");

设置车轮的motorTorque可以使车轮滚动！

FrontLeftWheel.steerAngle = 10 * Input.GetAxis("Horizontal");

FrontRightWheel.steerAngle = 10 * Input.GetAxis("Horizontal");

设置车轮的steerAngle可以控制车轮围绕自身Y轴的转向角度！这里的旋转角度是-10度到10度之间！

作者疑问：

第57,58,60,61行代码，

FrontLeftWheel.motorTorque = EngineTorque / GearRatio[CurrentGear] * Input.GetAxis("Vertical");

Input.GetAxis("Vertical")会返回-1，也就是说motorTorque是负值！

但是官方文档却说，

在轮轴上的电机力矩。根据方向正或负。

To simulate brakes, do not use negative motor torque - use brakeTorque instead.

模拟刹车，不要使用电机力矩负值，使用brakeTorque代替。

这两种说法之间可有冲突，请高手指点！

下篇是车轮与其他物体的碰撞，待续……！