Unity3d 赛车车辆各类性能算法---总结(转)

111 篇文章 3 订阅

致力于赛车性能算法已有多时,在确定赛车最终版本之时,做下总结。
文章还是不会非常详尽,点到为指,不想太多利用工作时间。

在制作前,必须先了解真实车辆的原理:
车辆分前轮驱动,后轮驱动和四驱动。动力由引擎提供,反应的力到轮胎上,因此产生转数,即RPM。
引擎的功率可以由RPM得到公式为 : RPM = 引擎功率×60/2×pi , 这些都是模拟,只为了更好的为下面的动作服务。还有大众关心的“漂移” ,所谓 漂移就是,在后驱车辆中,前轮方向旋转大角度,地面给于一定向心力,同时后轮又给予更多动力,导致“漂移”动作。

基于上面原理,就更容易理解下面的文章。 

我先说明,有非常多种方法来开发一款赛车。本人赛车版本经过无数多种方法,无数次改版后最终选了个大众接受的。这些方法,容我一个个道来。

首先,你要明白,车辆不可能整个套一个外壳,原因是在接触地面时,对车辆所使的力不可能达到你预期的目标,引起,必须在车辆轮胎以上做外壳碰撞,轮胎以下就需要有力来支持它始终保持不掉下来。

Unity3d里有个很神奇的东西 叫WheelCollider , 它是专门模拟轮胎支持力和轮胎转数,以及轮胎横向力,前进力,以及 悬架避震系统。
这个东西非常方便,只要你把这个东西套在4个轮胎上,调试下他的
forwardFriction 和sidewaysFriction
达到你想要的效果,然后对驱动轮的
motorTorque进行赋值,你的车辆就能动了。
记得你需要无数次调试 前进摩擦力和横向摩擦力 。 至于悬架系统在你需要时也可以改变其值。还有,这两个摩擦力,是一个由低到高,再由高到稳定的一条曲线。

这个WheelCollider非常好用,曾一度沉迷于此。但后来发现,他有很多不合理的地方。想要得到最好的效果,还是抛弃了他。

为了支持车辆的碰撞外壳不接触地面,必须写一个悬架动态支持力,在4个轮胎位置,支持整辆车悬浮于地面之上。
关于这个悬架动态支持力在这奉献下:

void SuspensionHoldForce()
{
     float fullCompressionSpringForce = this.rigidbody.mass * 0.25f * 2.0f * -Physics.gravity.y;
     this.OnGround = true;

     foreach( GameObject item in FwheelModels )
    {
         RaycastHit hit;
         bool onGround = Physics.Raycast( item.transform.parent.position , -item.transform.parent.InverseTransformDirection(Vector3.up), out hit, this.suspensionTravel + this.radius);

         if (onGround && hit.collider.isTrigger)
        {
            onGround = false;
            float dist = this.suspensionTravel + this.radius;
            RaycastHit[] hits = Physics.RaycastAll( item.transform.parent.position , -item.transform.parent.InverseTransformDirection(Vector3.up) , this.suspensionTravel + this.radius );
            foreach(RaycastHit test in hits)
           {
                if (!test.collider.isTrigger && test.distance <= dist)
               {
                     hit = test;
                     onGround = true;
                     dist = test.distance;
               }
           }
        }

        if( onGround )
        {
             Vector3 wheelVelo = this.rigidbody.GetPointVelocity (item.transform.parent.position);
             Vector3 localVelo = transform.InverseTransformDirection (wheelVelo);
             Vector3 groundNormal = transform.InverseTransformDirection (hit.normal);
             float damperForce = Vector3.Dot(localVelo, groundNormal) * 5000f;
             float compression = 1.0f - ((hit.distance - radius) / suspensionTravel);
             Vector3 springForce = ( fullCompressionSpringForce*compression - damperForce ) * item.transform.parent.InverseTransformDirection(Vector3.up);

             springForce.z = springForce.x = 0f;

             this.rigidbody.AddForceAtPosition( springForce , item.transform.parent.position );

         }
         else
        {
            this.OnGround = false;
        }
    }

    foreach( GameObject item in BwheelModels )
    {
         RaycastHit hit;
         bool onGround = Physics.Raycast(  item.transform.parent.position, -item.transform.parent.InverseTransformDirection(Vector3.up), out hit, this.suspensionTravel + this.radius);

         if (onGround && hit.collider.isTrigger)
         {
               onGround = false;
               float dist = this.suspensionTravel + this.radius;
               RaycastHit[] hits = Physics.RaycastAll( item.transform.parent.position, -item.transform.parent.InverseTransformDirection(Vector3.up) , this.suspensionTravel + this.radius );
               foreach(RaycastHit test in hits)
               {
                     if (!test.collider.isTrigger && test.distance <= dist)
                     {
                           hit = test;
                           onGround = true;
                           dist = test.distance;
                      }
                }
           }

           if( onGround )
          {
                Vector3 wheelVelo = this.rigidbody.GetPointVelocity (item.transform.parent.position);
                Vector3 localVelo = transform.InverseTransformDirection (wheelVelo);
                Vector3 groundNormal = transform.InverseTransformDirection (hit.normal);
                float damperForce = Vector3.Dot(localVelo, groundNormal) * 5000f;
                float compression = 1.0f - ( ( hit.distance - radius ) / suspensionTravel );
                Vector3 springForce = ( fullCompressionSpringForce*compression - damperForce ) * item.transform.parent.InverseTransformDirection(Vector3.up);
                springForce.z = springForce.x = 0f;
                this.rigidbody.AddForceAtPosition( springForce , item.transform.parent.position );
          }
          else
         {
               this.OnGround = false;
          }
     }
}
那么在完成悬架支撑后,就该设计车辆动力了。
这里也有2种方法:一个方向是真实车辆行驶轨迹,另一个是模拟型车辆轨迹。
前者的方法是 , 将动力点放在车辆驱动轮上,例如后轮。用rigidbody的
AddForceAtPosition可以做到,前轮只需要提供横向力就可以实现转弯的轨迹。但别看说说这么容易,这里面还涉及非常多的数值和曲线问题。在提供车辆动力时,你需要一条曲线,以致车辆不会匀加速,因为这样很不真实,还有在前轮横向力中,你必需是条由0到最高点,然后下降到平衡点的曲线。这样你的赛车才显得更真实。这些都需要用到几个数学知识。
后者,是用算法来模拟的一种车辆轨迹。这个算法所有作用力作用在车辆的中心点。
转弯轨迹,我是用转弯半径来表示,使得车辆在转弯时有相当的真实性,必须改变车辆转弯速度。当然,用到了些数学知识。代码奉献下:

#region 计算转弯角度
void Steering( bool canSteer , Vector3 relativeVelocity )
{
     if( canSteer && this.OnGround )
    {
          if( this.shiftthrottle == 1 )
         {
              this.transform.RotateAround( this.transform.TransformPoint( ( this.FwheelModels[0].transform.localPosition + this.FwheelModels[1].transform.localPosition) * 0.5f ) , this.transform.up , this.rigidbody.velocity.magnitude *2f* this.steeringInput * Time.deltaTime * 2f );
              //~ this.rigidbody.AddForceAtPosition( this.FwheelModels[0].transform.TransformDirection(Vector3.right*this.steeringInput) * 3f * this.rigidbody.mass, this.FwheelModels[0].transform.position);
             //~ this.rigidbody.AddForceAtPosition( this.FwheelModels[1].transform.TransformDirection(Vector3.right*this.steeringInput) * 3f * this.rigidbody.mass, this.FwheelModels[1].transform.position);
             return ;
         }

        if( this.throttle * this.transform.InverseTransformDirection(this.rigidbody.velocity).z < 0 )
             return ;

       float turnRadius = 3.0f / Mathf.Sin( (90f - this.steering) * Mathf.Deg2Rad );
       float minMaxTurn = EvaluateSpeedToTurn(this.rigidbody.velocity.magnitude);
       float turnSpeed = Mathf.Clamp(relativeVelocity.z / turnRadius, -minMaxTurn / 10, minMaxTurn / 10);
       this.transform.RotateAround( this.transform.position + this.transform.right * turnRadius * this.steeringInput , transform.up , turnSpeed * Mathf.Rad2Deg * Time.deltaTime * this.steeringInput );

       //~ Vector3 debugStartPoint = transform.position + transform.right * turnRadius * this.steeringInput;
       //~ Vector3 debugEndPoint = debugStartPoint + Vector3.up * 5f;

       //~ Debug.DrawLine(debugStartPoint, debugEndPoint, Color.red);
    }
}

float EvaluateSpeedToTurn( float speed )
{
     if(speed > this.topSpeed / 2)
         return minimumTurn;
     float speedIndex = 1 - ( speed / ( this.topSpeed / 2 ) );
     return minimumTurn + speedIndex * (maximumTurn - minimumTurn);
}
#endregion

这个模拟车辆轨迹,不能达到漂移的性能,但我加了一个滑动比例计算的算法,用车辆横向移动速度,和前进速度,的比例来确定,该车辆是否处于漂移状态,如处于,则启动漂移滑动程序。当然,我的赛车是很自然的,不做做。至于轮胎痕迹,就是判断是否触底后,在该点生成轮胎痕迹gameobject,如此而已。

最后,再介绍下,所有车辆都需要模拟的,行驶时,轮胎随速度旋转这个关系到车辆看起来真实性的东西。其实非常简单。不多说,发代码:

#region 轮胎滚动与旋转模拟
void WheelRoll()
{
      float averageAngularVelo = ( this.rigidbody.GetPointVelocity(this.BwheelModels[0].transform.parent.position).magnitude + this.rigidbody.GetPointVelocity(this.BwheelModels[0].transform.parent.position).magnitude )/2f;
      float engineAngularVelo = averageAngularVelo * 3f;

      float rpm = engineAngularVelo * (60.0f/(2*Mathf.PI)) * (this.transform.InverseTransformDirection(this.rigidbody.velocity).z > 0f ? 1f : -1f );

      //~ Debug.Log(this.transform.InverseTransformDirection(this.rigidbody.velocity).z);

      FwheelModels[0].transform.rotation = FwheelModels[0].transform.parent.rotation *     Quaternion.Euler (RotationValue, this.steering , 0);//旋转
      FwheelModels[1].transform.rotation = FwheelModels[1].transform.parent.rotation * Quaternion.Euler (RotationValue, this.steering , 0);//旋转

      BwheelModels[0].transform.rotation = BwheelModels[0].transform.parent.rotation * Quaternion.Euler (RotationValue, 0, 0);//旋转
      BwheelModels[1].transform.rotation = BwheelModels[1].transform.parent.rotation * Quaternion.Euler (RotationValue, 0, 0);//旋转

      RotationValue += rpm * ( 360f/60f ) * Time.deltaTime;
}

#endregion

http://www.cnblogs.com/lm3515/archive/2010/09/21/1832324.html

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Vehicle physics package suitable for wide range of vehicles. Realistic, easy to use and heavily customizable. Wheel Controller 3D, a custom in-house wheel solution, has been used for wheel physics while the rest of the system had been written from the ground up. General features: • Fast vehicle setup with quick start video or included manual. • Seven vehicle prefabs of different types are included: sports car, sedan, 8x8 truck, monster truck, tank, city bus and semi with trailer. • Suitable for wide range of applications. • Runs on both desktop and mobile devices. • Uses custom in-house wheel solution – Wheel Controller 3D – for 3D ground detection and high level of customizability. • Per-wheel surface detection based on terrain textures or object tags. Different friction curves and effects for each surface. • Suspend option for inactive vehicles which minimizes impact on performance while keeping basic functionality. • Character vehicle changer that works with any character controller / game object, including other vehicles. • Helper scripts such as analog and digital gauge controllers, camera and vehicle changers, center of mass and downforce adjusters, etc. Vehicle Physics Details: Engine • Realistic engine power and torque calculation with adjustable power curve and RPM range. • Functional forced induction. Transmission • Gear ratios and final gear ratio. • Dynamic shift point based on load. • Three transmission types: Automatic, Automatic Sequential and Manual. • Manual transmission supports both sequential and H-pattern shifting. • Center differential: Open, Limited Slip, Locking or Equal. Axles • Geometry settings for each axle: Steering Angle, Pro/Anti Ackermann Steering, Toe, Camber, Caster and Anti-roll Bar. • Adjustable power, braking and handbrake distribution. • Per-axle differentials: Open, Limited Slip, Locking and Equal. • Supports solid axle (check Monster Truck in the demo). Damage • Optimized queue-based mesh deformation that spreads processing over multiple frames. • Damage influences vehicle performance and handling. Audio • All audio sources are set up automatically. • Sound can be adjusted through Audio Mixer for all vehicles or though inbuilt mixer for each vehicle and each effect individually. • Engine, forced induction, gear change, suspension, surface, skid, crash, air brake, horn and blinker sounds. Effects • Vehicle light system with low beam, high beam, stop and brake lights, blinkers. • Can be used with any number of lights of any type and/or emissive materials. • Persistent and well optimized mesh-based skidmarks. • Exhaust particle effects based on engine state. • Per-wheel dust and smoke particle effects based on surface the wheel is on. Input • Desktop input using standard input manager with mouse steering option. • Mobile input through on-screen steering wheel and pedals or tilt controls. Trailer • Trailer is a vehicle in itself meaning all the effects that work on a vehicle work on a trailer too. • Trailer gets input routed from the vehicle it is attached to which results in functional lights, braking, damage and even steering if needed. • Built-in attach / detach functionality where any vehicle can attach any trailer with correct tag. Fuel • Fuel consumption calculation using engine’s efficiency. • Readouts in l/100km, km/l and US mpg. UI • Universal analog and digital gauge controllers and lights for use in dashboard or HUD. Code • Modular code structure for easy modification and upgrading. • C# source code with XML comments on all public members. • Tooltip explanations for all visible variables. Compatible With Complete Terrain Shader and IK Driver Vehicle Controller European Truck and Trailer and Super Car models provided by GAME READY 3D MODELS . Try it out: Windows 64bit MacOS X 64bit Android (mobile scene) More info: Website Unity Forums YouTube Class Reference Changelog Note: Wheel Controller 3D is included with this asset and its price has been factored in. If you already own WC3D check the upgrade options. If you have any questions. problems or suggestions you can contact us at nwhcoding@gmail.com. Support is free and we always answer within a few hours.
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值