【Unity】【翻译搬运】使用WheelColliders做出稳定真实的车

说在前面

首先,作为尊敬这位大神的工作成果,贴出原帖的位置:
http://forum.unity3d.com/threads/how-to-make-a-physically-real-stable-car-with-wheelcolliders.50643/
(请大家搬运转载的时候,尊重原作,连同上面信息一起转载。不仅是诚意贴,而且WheelColliders的文献有干货的真的难找。。)
翻译水平有限,也请各位读者海涵。如果各位想了解WheelCollider怎么使用,可以参照Car Physics示例(链接:http://pan.baidu.com/s/1kTjIQ4f 密码:02n9)。本篇不对基本使用方法做叙述,侧重怎样调整WheelCollider与程序配合表现出真实效果。
转载请注明,出自喵喵丸的博客 (http://blog.csdn.net/u011643833/article/details/49102423)


搬运正文

【下面出现如这个形式与颜色的部分为我自己添加的注释】


Part1 Demo说明以及几条建议

Demo地址:http://www.edy.es/dev/vehicle-physics/live-demo
【Unity】【翻译搬运】使用WheelColliders做出稳定真实的车_第1张图片
Enter——重新开始,当你翻车或者跑出了Terrain
H——获取帮助【我发现原帖中介绍的按键有些已经不是他曾经说明的功能了,所以大家还是点开H,查看按键说明(在回帖中发现是论坛不容许贴主编辑原文,所以把相关更新都写在了回帖中,我也相应的卸载了回帖总结的部分里面)】
【另外:提供了几种车辆常用的系统,我粗略试了一下TC和4x4/rear(剩余应该也可以工作),其余的几种只因为我不太了解工作起来的表现,只能请各位自己试试咯~
ABS:防抱死、TC:循迹防滑控制系统、ESP:电子车身稳定系统、 4x4/rear:四驱/后驱】

【Unity】【翻译搬运】使用WheelColliders做出稳定真实的车_第2张图片

Demo中演示的不仅是一个典型公路车不太平稳的样子,而且在背后负重了一直500KG(1100磅)重的盒子。你可以尝试在Demo中的各个地形上行车使这个盒子保持不掉下去。【这是进入Demo后的第一个演示车(越野车)的状态,Demo中还有跑车以及公交车的演示】

建议Notes:

  • 车子的简单物理模型:刚体Rigidbody + 基于车子形状的组织的一些BoxCollider + 4个wheelCollider
  • RigidBody的centerOfMass的设定在车子的前座附近【Rigidbody.centerOfMass 质量中心 相对于变换原点的质心。如果你不在脚本中设置质心,它将从所有附加到刚体上的碰撞器自动计算,当模拟汽车使它们更加稳定时,设定质心是非常有用的。具有较低质心的汽车不太容易翻车。】

  • 不要设置刚体RigidBody上AngularDrag(角阻力), 不要给车子设定其他作用力

  • WheelCollider中轮胎的摩擦系数使用默认值,只调整 Forward Friction/Stiffness Factor(正向摩擦/刚度系数)以及Sideways Friction/Stiffness Factor(横向摩擦/刚度系数),分别为Forward0.82、SideWays:0.022
  • 运行时不修改任何参数,不论是Rigidbody.centerOfMass(质量中心)、rigidbody其他参数、wheelCollider的suspension(悬挂系数)还是其他的参数

Part2 WheelCollider使用常见问题分析

Q:一部用刚体Rigidbody和4个WheelCollider构成的的车,在转弯时为何特别容易翻车
A:因为现实生活中的车,就是这么容易翻!

在Unity中创建的车子填充了真车的数据(质量、尺寸等),添加了控制车辆的脚本跑起来的那一刻,你就会发现,一点点的速度就会使你的车在拐角处轻易的翻车。如果同样的车可以出现在现实生活中,也会是同样的表现。PhysX并不完美,可是他可以相当好的还原与真实物体类似的物理行为。
你可以创建一个WheelCollider观察他的摩擦曲线参数Friction,里面的参数默认为(1,20000,2,10000,1),这几乎是无限抓地力的一组轮胎系数,所以当车子运动起来只能是较低的速度,所以首先要做的是,将Stiffness Factor刚度系数调整到0.01-0.03之间,这样轮胎会更像现实中的表现。但是在这种情况下,还是会翻车。
【这里提供三个wheelCollider说明的网址
WheelCollider说明(中文)
WheelCollider说明(UnityManual)
WheelCollider使用指引(UnityManual)】

Q:但是现实中的车为什么并不像你说的那么容易就翻?
A:因为现实生活中的车有一种叫做平衡杆(又名防侧倾杆或防摇杆)的装置

首先来科普一下,平衡杆是怎么工作的(依旧是英文文献。。)【这时候就勇敢的去百度一下平衡杆】

当现实生活中的车发生急转的时候,车辆的外侧轮胎向下贴近路面,车辆的内侧轮胎被抬高。换一种说法,这时的车子向着外侧旋转了10°、20°或者更多。如果这时车的速度够快,这种向着外侧发生的旋转就会引起翻车,这种情形是否和你刚才做过的翻车实验很像?
稳定杆连接了同一根轴上面两个轮胎,限制这两个轮胎之间的自由度。当一侧的轮胎抬起的时候,平衡杆会将力分解到另一侧的轮胎以及悬挂系统之上,这样就限制了车身在这个轴向上的旋转。
如果没有平衡杆,车身会在转弯发生的时候发生翻车,如果平衡杆做的太过,那么两侧的悬挂系统又会失去独立性。

Q:平衡杆什么的根本没听过,真的这么重要么?
A:当然,平衡杆是车辆悬挂系统的重要组成部分,和车子的弹簧和阻尼器一样重要。

你可以观察一下现实中车子的前轮内侧,你可以看到一个连接两端悬挂系统的刚性杆,这就是我们说的平衡杆。现实中只有很少的一部分车子使用了类似液压控制系统的动态系统来模仿实现平衡杆的作用。
在Unity中使用WheelCollider,其实有官方的文档做了一些使用示范,可是稳定的WheelCollider应该包含怎样的参数内容,以及平衡杆相关内容几乎没有提及。

Q:那么之前提及的建议(更低的质心,角阻力,自定义的轮胎摩擦系数…)有何作用?
A:就是为了让你的车变得像是安装了平衡杆一样的基础条件。

当你真正的有一辆具备了刚体Rigidbody + 4个WheelCollider + 2组平衡杆(前轮后轮各一组)的车子,你才可以在技术上对你的车子进行其他方面的调整,比如手感、或者其他驾驶风格的车子。
你会发现即使是构成上如此简单的一部车,也会有很多可以调整和选择部分,这些都可以帮助你创造出不同手感和驾驶体验的车子,举例说明一下:质量Mass、质心位置centerOfMass(通常会向发动机所在位置放)、前后轮弹簧系数Spring、前后轮阻尼系数Dampers(前后轮必须不同,引擎所在的轴需要提供更多的支撑力)、前后轮的刚度系数Striffness…
你可以把复杂的摩擦系数、阻力系数留到最后再考虑,这样你可以看到只调整前后轮的刚度系数Striffness,会对平衡杆造成的影响,从而造成的手感不同。

Q:质心CenterOfMass的降低,会带来什么不利的影响
A:会使得跳跃、碰撞、撞击和空中的姿态看起来奇怪一些

利用手动设置质心的方式会使得某一些运动的情况变好,但是另外一些情况下显得奇怪起来。如果你调整了质心CenterOfMass,使得它更趋近真实,平衡杆的效应会使得所有的运动情况都趋向于真实。

Q:你说了这么多。可是我在运行Demo的时候,跑车模式下转弯翻车了!
A:如果你在现实中开了这样一辆车,并在高速模式下转急弯。你真的会像是Demo里一样的翻车的。

如果你看过一些关于车子纪录片,你会明白这类跑车即使在正常的速度下也很容易翻车。你可能知道一种叫做麋鹿测试(The moose test)的东西【此处可百度麋鹿测试,有图示】,以80km/h通过密集的S弯道,现实中有很多车都没能通过这个测试。
而且,Demo中车子质心CenterOfMass的高度是位于车高一半的附近!如果你想让他在“赛车”模式之下翻车,你需要在60Km/h的速度下进行急转,这种情况才翻车,平衡杆已经起到了很大的作用了。
【Unity】【翻译搬运】使用WheelColliders做出稳定真实的车_第3张图片


Part3 干货

Q:Unity里如何模拟出平衡杆呢?
A:很容易(。・∀・)ノ゙

平衡杆的工作方式将力是从一侧的弹簧传递向同一轴另一侧,传递的量取决于两轮之间悬挂的差异。
所以首先需要计算在地面以及不在地面时每个轮子不同的悬挂变化。我们期望变化的值在0.0(完全压缩)与1.0(完全扩展)之间


groundedL = WheelL.GetGroundHit(hit))
if (groundedL)
    travelL = (-WheelL.transform.InverseTransformPoint(hit.point).y - WheelL.radius) / WheelL.suspensionDistance;
else
    travelL = 1.0;

我们将平衡杆弹簧可传递的最大的力称为平衡杆刚度系数(即:下面代码中提到的变量AntiRoll),接下来我们将轴两端悬挂差异的值与平衡杆的刚度系数想乘,计算结果即是平衡杆传递的力的大小。

var antiRollForce = (travelL - travelR) * AntiRoll

最后,我们需要将计算出来的力从一侧减掉,并且添加到另一侧的轮子上。这个过程我们通过从轮胎Wheelcollider所在位置向刚体Rigidbody添加反向作用力来实现。

if (groundedL)
    rigidbody.AddForceAtPosition(WheelL.transform.up * -antiRollForce, WheelL.transform.position);
if (groundedR)
    rigidbody.AddForceAtPosition(WheelR.transform.up * antiRollForce, WheelR.transform.position);

Q:平衡杆的刚度系数(AntiRoll的值)取多少合适?他的单位是什么?
A:合适的取值大致是轮子的Spring的取值,单位同样是牛顿(N)【这个地方我去翻找了一下WheelCollider中Suspension Spring/Spring 的描述,还真是弹簧力(:з」∠)所以单位为牛顿】

Spring的值表示弹簧完全压缩的时候,能够提供的力。而AntiRoll的值表示从一侧传递向另一侧的力的大小。同一根轴上面的Spring和AntiRoll两者同样大小意味着平衡轴可以将全部的力传递到另一边。

Q:求一份平衡杆的脚本代码
A:给!【贴主Edy真仁义,给出的是JS的代码,大家有需要C#自行翻译一下,至于代码的意义上面巨大的篇幅已经阐述过了】

【贴主Edy觉得Unity官方将平衡杆相关的代码加入Standard Assets内,这篇帖子是2010年的,可是我15年使用4.6还没有相关的代码(:з」∠)所以肯定不只我一个觉得WheelCollider用起来不知所措】
在车辆上添加两个平衡杆脚本,前后平衡轴各一个,调整轴左右轮胎WheelCollider的参数设定与平衡杆相匹配。记住要重新设置质心位置(或者完全不要动质心的位置)。
下面是完整的脚本 AntiRollBar.js

var WheelL : WheelCollider;
var WheelR : WheelCollider;
var AntiRoll = 5000.0;

function FixedUpdate ()
{
    var hit : WheelHit;
    var travelL = 1.0;
    var travelR = 1.0;

    //计算两侧轮胎在不同情况下的悬挂系数
    var groundedL = WheelL.GetGroundHit(hit);
    if (groundedL)
        travelL = (-WheelL.transform.InverseTransformPoint(hit.point).y - WheelL.radius) / WheelL.suspensionDistance;

    var groundedR = WheelR.GetGroundHit(hit);
    if (groundedR)
        travelR = (-WheelR.transform.InverseTransformPoint(hit.point).y - WheelR.radius) / WheelR.suspensionDistance;

    //计算平衡杆刚度系数
    var antiRollForce = (travelL - travelR) * AntiRoll;

    //向两侧的轮胎分配力
    if (groundedL)
        rigidbody.AddForceAtPosition(WheelL.transform.up * -antiRollForce, WheelL.transform.position);  
    if (groundedR)
        rigidbody.AddForceAtPosition(WheelR.transform.up * antiRollForce, WheelR.transform.position);  
}

Q:如何给车设置真正的质心
A:使用不重合的BoxCollider按照车子的形状围起来,然后把中心移动引擎处。

【Unity】【翻译搬运】使用WheelColliders做出稳定真实的车_第4张图片

Unity/PhysX的质心CenterOfMass是基于碰撞盒的位置和体积计算的,需要注意的是,重叠的Collider会在重叠部分增加多余的质量。
通常情况下,你需要把质心CenterOfMass向发动机位置移动一些。例如:如果车子的引擎靠前并且对于车子来讲前方为Z轴正方向,你只需要将质心向前移动1m,剩下的程序会帮你自动计算。

function Start()
{
    rigidbody.centerOfMass += Vector3(0, 0, 1.0);
}

Q:这么简单的处理真的能有良好的表现么?
A:那么你可以到这里来体验下:http://www.edy.es/dev/vehicle-physics/live-demo

你可以切换到车里的视角观察车子的运动、也可以观察整体的运动状况,等等…
【可以潇洒的漂移!而且引擎的声音处理的也很搭。最最重要的手感十分稳定真实】


Part4 作者Edy的结语
【以下是作者Edy的一些自我介绍,不感兴趣的同学可以直接跳过来阅读下面的回帖部分】
这是我在这里的第一次发帖,请允许我介绍一下自己,我现在工作于 dj software,几年前,当我还是学生的时候,曾经和我的两个同学尝试使用C++在无引擎的情况下开发游戏,只因为自己从小就想要做这样的事情。如你想象的一样,我们几乎没有成果。我在4周前我发现了Unity(之前虽然听说过,但是并没有尝试),这对我来说简直是看到了光。我只需要将我想要的东西拖入场景,点击播放,他便可以运行了!我查看示例代码并使用Unity用的语言进行调整(知道两周前我才发现是JavaScript)。这简直像是魔法,现在我正在实现一个自己从小就有的梦想——想要通过之前学习的Basic或者命令行来实现的物理真实的车辆模型,不仅如此,还可以简单做出各种各样的车辆体验!即使是作为一个爱好者,出于对Unity的热爱购买了付费版本。
这是我第一次对Unity社区做出贡献。使用Unity车辆物理模型非常有趣。
Enjoy!
Edy


Part5 回帖摘录
【帖子过去很久了,有一部分图片我已经看不到了,所以,问题的一部分情况依靠脑补】

  1. 问题现象:不论mass/Spring/Damping的值如何调整,车速一直很低
    问题解决:
    ① Sideways Friction /Stiffness Factor值为1,所有车轮上面的这一项值都应该在0.01-0.02之间,微调这个值可以让车子的“漂移”呈现不同的状态【这里做个说明吧,其实作者Edy前后几次都提到了关于横向摩擦的刚度系数Sideways Friction /Stiffness Factor取值范围,但是每次给出的范围都不太一样,这里作为我个人的猜测,这里存在问题的车辆应该是一种以漂移为主要手感的车,所以Edy给出的范围为0.01-0.02。我自己进行试验的时候调整到0.01-0.02范围内,车尾在转弯的时候已经摆的非常大了。所以各位可以自己测试一下横向摩擦刚度系数对自己的车子手感造成多大影响,测试时候可以按照Edy在更后面回帖中提出的从0.04开始向更小或者更大取值测试,一般不会低于0.01,也不会高于0.06太多(自己测试0.06转弯已经非常的笨了)】
    ② 车轮的半径Radius太大,半径要更现实一些,大约为0.5。需要注意的是,半径也在增加你车辆的高度
    ③ 车身的上部存在了一个过大的Collider,这使得自动计算的质心CenterOfMass将会非常高,这时需要将质心移动到一个更真实的点上,在更靠下的地方会更好。

  2. 贴主提到了Demo新的更新内容
    【Unity】【翻译搬运】使用WheelColliders做出稳定真实的车_第5张图片
    ① 做了许多改进
    ②变成了四辆车(皮卡/ GTA4 中的皮卡/ 公共汽车/跑车)可使用PageUp/PageDown来进行切换
    ③增添可以显示速度、转速、和其他行驶参数的仪表盘
    ④ 改进了碰撞变形损伤、修复的脚本
    ⑤ 视角切换为车内时,可以移动鼠标观察车内情况(F1切换车内)
    ⑥ 公交车可以使用公交司机的后视镜视角(F1)
    ⑦ 低速时更好的模拟摩擦力
    ⑧ 漂移撞击时候更好的烟效
    ⑨ 图像来体现轮胎参数(B 以及ShiftB)
    【关闭TC可以在地面上漂移处帅气轮胎印】

  3. 问题现象:让车向前就会翻车
    问题解决:forwardFriction.stiffnessFactor 的值过高,应该在0.02-0.08之间取值。同时还需要将你设置的motorTorque/brakeTorque的值变小,不要参照真实的数值,自己调整数值尝试直到他正常工作。
    【这里我提供中英两处关于WheelCollider脚本Api
    Unity圣典 WheelCollider(中文)
    Untiy Manual WheelCollider】

  4. 一个很常见的问题:当车速爬升过一定的速度之后,翻车将会变得特别容易
    Unity提供的WheelCollider存在这样一个设计缺陷:速度变大时 SidewaysFriction将大大增加。解决方法是限制你车辆的最大速度,找到一个sideways stiffness、质心高度CenterOfMass、平衡杆刚度之间的合适平衡,这个平衡可以使得车辆在最大速度之下只发生侧滑。sideways stiffness的取值从0.04开始尝试,最后将值固定在0.02-0.06之间,这样这个问题就能很好的解决了。
    【一点个人猜想:GTA5中越好开(操作容易)的车越是破,豪车非常难以操控 是不是也是这个道理呢(:з」∠)(一点点猜想)】

写在最后

欢迎各位留言指正~
再次感谢贴主Edy容许我转载翻译~
原帖地址http://forum.unity3d.com/threads/how-to-make-a-physically-real-stable-car-with-wheelcolliders.50643/
【Unity】【翻译搬运】使用WheelColliders做出稳定真实的车_第6张图片
【Unity】【翻译搬运】使用WheelColliders做出稳定真实的车_第7张图片
转载请注明,出自喵喵丸的博客 (http://blog.csdn.net/u011643833/article/details/49102423)

你可能感兴趣的:(Unity,unity,collider,PhyX,vehicel,wheel)