unity3d的动力学汽车脚本

来源:互联网 发布:c语言字符串头文件 编辑:程序博客网 时间:2024/05/16 17:27

/*unity3d的动力学汽车脚本 收藏

 

这是从官网论坛上收集的一个汽车脚本,经过验证可以使用。由于skidmarks这个配套的脚本没有找到,

 

所以把skidmarks相关的语句都屏蔽了,所以很遗憾没有刹车印的效果,其他的没有改。

 

使用方法如下:

 

    1、把脚本直接连到汽车车身网格上,车身要有Rigidbody Component,要有四个轮子网格做子物体。 要想有声音的话还要有AudioSourceComponent。

 

    2、打开Inspector,选择汽车脚本,把四个轮子连接到相对应的Transform参数上。设置wheelRadius参数为你轮子网格的大小。WheelCollider是自动生成的,所以无需手动添加。这样就能保证运行了,其他的声音和灰尘可以再添加。

 

    脚本源代码如下:*/

#pragma strict

//maximal corner and braking acceleration capabilities

var maxCornerAccel=10.0;

var maxBrakeAccel=10.0;

//center of gravity height - effects tilting incorners

var cogY = 0.0;

//engine powerband

var minRPM = 700;

var maxRPM = 6000;

//maximum Engine Torque

var maxTorque = 400;

//automatic transmission shift points

var shiftDownRPM = 2500;

var shiftUpRPM = 5500;

//gear ratios

var gearRatios = [-2.66, 2.66, 1.78, 1.30, 1.00];

var finalDriveRatio = 3.4;

//a basic handling modifier:

//1.0 understeer

//0.0 oversteer

var handlingTendency = 0.7;

//graphical wheel objects

var wheelFR : Transform;

var wheelFL : Transform;

var wheelBR : Transform;

var wheelBL : Transform;

//suspension setup

var suspensionDistance = 0.3;

var springs = 1000;

var dampers = 200;

var wheelRadius = 0.45;

//particle effect for ground dust

var groundDustEffect : Transform;

private var queryUserInput = true;

private var engineRPM : float;

private var steerVelo = 0.0;

private var brake = 0.0;

private var handbrake = 0.0;

private var steer = 0.0;

private var motor = 0.0;

//private var skidTime = 0.0;

private var onGround = false;

private var cornerSlip = 0.0;

private var driveSlip = 0.0;

private var wheelRPM : float;

private var gear = 1;

//private var skidmarks : Skidmarks;

private var wheels : WheelData[];

private var wheelY = 0.0;

private var rev = 0.0;

//Functions to be used by external scripts

//controlling the car if required

//===================================================================

//return a status string for the vehicle

function GetStatus(gui : GUIText) {

  gui.text="v="+(rigidbody.velocity.magnitude *3.6).ToString("f1") + " km/h\ngear= "+gear+"\nrpm="+engineRPM.ToString("f0");

}

//return an information string for the vehicle

function GetControlString(gui : GUIText) {

  gui.text="Use arrow keys to control the jeep,\nspace forhandbrake.";

}

//Enable or disable user controls

function SetEnableUserInput(enableInput)

{

  queryUserInput=enableInput;

}

//Car physics

//===================================================================

//some whee calculation data

class WheelData{

   var rotation= 0.0;

   var coll :WheelCollider;

   var graphic :Transform;

   varmaxSteerAngle = 0.0;

   varlastSkidMark = -1;

   var powered =false;

   varhandbraked = false;

   varoriginalRotation : Quaternion;

};

function Start () {

   //setupwheels

   wheels=newWheelData[4];

  for(i=0;i<4;i++)

      wheels[i]= new WheelData();

      

  wheels[0].graphic = wheelFL;

  wheels[1].graphic = wheelFR;

  wheels[2].graphic = wheelBL;

  wheels[3].graphic = wheelBR;

  wheels[0].maxSteerAngle=30.0;

  wheels[1].maxSteerAngle=30.0;

   wheels[2].powered=true;

  wheels[3].powered=true;

  wheels[2].handbraked=true;

  wheels[3].handbraked=true;

   for(w inwheels)

   {

     if(w.graphic==null)

        Debug.Log("You need to assign all four wheels for the carscript!");

     if(!w.graphic.transform.IsChildOf(transform))   

        Debug.Log("Wheels need to be children of the Object with the carscript");

         

     w.originalRotation = w.graphic.localRotation;

      //createcollider

     colliderObject = new GameObject("WheelCollider");

     colliderObject.transform.parent = transform;

     colliderObject.transform.position = w.graphic.position;

      w.coll =colliderObject.AddComponent(WheelCollider);

     w.coll.suspensionDistance = suspensionDistance;

     w.coll.suspensionSpring.spring = springs;

     w.coll.suspensionSpring.damper = dampers;

      //no grip,as we simulate handling ourselves

     w.coll.forwardFriction.stiffness = 0;

     w.coll.sidewaysFriction.stiffness = 0;

     w.coll.radius = wheelRadius;

   } 

   //get wheelheight (height forces are applied on)

  wheelY=wheels[0].graphic.localPosition.y;

   

   //setupcenter of gravity

  rigidbody.centerOfMass.y = cogY;

   

   //findskidmark object

//   skidmarks =FindObjectOfType(typeof(Skidmarks));

   

   //shift tofirst

   gear=1;

}

//update wheel status

function UpdateWheels()

{

   //calculatehandbrake slip for traction gfx

   handbrakeSlip=handbrake*rigidbody.velocity.magnitude*0.1;

  if(handbrakeSlip>1)

     handbrakeSlip=1;

      

  totalSlip=0.0;

  onGround=false;

   for(w inwheels)

   {      

      //rotatewheel

      w.rotation+= wheelRPM / 60.0 * -rev * 360.0 * Time.fixedDeltaTime;

      w.rotation= Mathf.Repeat(w.rotation, 360.0);      

     w.graphic.localRotation= Quaternion.Euler( w.rotation,w.maxSteerAngle*steer, 0.0 ) * w.originalRotation;

      //check ifwheel is on ground

     if(w.coll.isGrounded)

        onGround=true;

         

      slip =cornerSlip+(w.powered?driveSlip:0.0)+(w.handbraked?handbrakeSlip:0.0);

      totalSlip+= slip;

      

      var hit :WheelHit;

      var c :WheelCollider;

      c =w.coll;

     if(c.GetGroundHit(hit))

      {

         //if the wheel touches the ground, adjustgraphical wheel position to reflect springs

        w.graphic.localPosition.y-=Vector3.Dot(w.graphic.position-hit.point,transform.up)-w.coll.radius;

         

        //create dust on ground if appropiate

        if(slip>0.5 && hit.collider.tag=="Dusty")

         {

           groundDustEffect.position=hit.point;

           groundDustEffect.particleEmitter.worldVelocity=rigidbody.velocity*0.5;

           groundDustEffect.particleEmitter.minEmission=(slip-0.5)*3;

           groundDustEffect.particleEmitter.maxEmission=(slip-0.5)*3;

           groundDustEffect.particleEmitter.Emit();                        

         }

         

         //andskid marks            

        /*if(slip>0.75 && skidmarks != null)

           w.lastSkidMark=skidmarks.AddSkidMark(hit.point,hit.normal,(slip-0.75)*2,w.lastSkidMark);

         else

           w.lastSkidMark=-1; */

      }

     // elsew.lastSkidMark=-1;

   }

  totalSlip/=wheels.length;

}

//Automatically shift gears

function AutomaticTransmission()

{

   if(gear>0)

   {

     if(engineRPM>shiftUpRPM&&gear<gearRatios.length-1)

         gear++;

     if(engineRPM<shiftDownRPM&&gear>1)

         gear--;

   }

}

//Calculate engine acceleration force for current RPMand trottle

function CalcEngine() : float

{

   //no enginewhen braking

  if(brake+handbrake>0.1)

      motor=0.0;

   

   //if car isairborne, just rev engine

   if(!onGround)

   {

      engineRPM+= (motor-0.3)*25000.0*Time.deltaTime;

      engineRPM= Mathf.Clamp(engineRPM,minRPM,maxRPM);

      return0.0;

   }

   else

   {

     AutomaticTransmission();

     engineRPM=wheelRPM*gearRatios[gear]*finalDriveRatio;

     if(engineRPM<minRPM)

        engineRPM=minRPM;

     if(engineRPM<maxRPM)

      {

         //fakea basic torque curve

         x =(2*(engineRPM/maxRPM)-1);

        torqueCurve = 0.5*(-x*x+2);

        torqueToForceRatio = gearRatios[gear]*finalDriveRatio/wheelRadius;

         returnmotor*maxTorque*torqueCurve*torqueToForceRatio;

      }

      else

         //rpmdelimiter

         return0.0;

   }

}

//Car physics

//The physics of this car are really a trial-and-errorbased extension of

//basic "Asteriods" physics -- so you willget a pretty arcade-like feel.

//This may or may not be what you want, for a morephysical approach research

//the wheel colliders

function HandlePhysics () {

   varvelo=rigidbody.velocity;

  wheelRPM=velo.magnitude*60.0*0.5;

  rigidbody.angularVelocity=newVector3(rigidbody.angularVelocity.x,0.0,rigidbody.angularVelocity.z);

  dir=transform.TransformDirection(Vector3.forward);

   flatDir=Vector3.Normalize(newVector3(dir.x,0,dir.z));

   flatVelo=newVector3(velo.x,0,velo.z);

  rev=Mathf.Sign(Vector3.Dot(flatVelo,flatDir));

   //when movingbackwards or standing and brake is pressed, switch to reverse

  if((rev<0||flatVelo.sqrMagnitude<0.5)&&brake>0.1)

      gear=0;

   if(gear==0)

   {   

      //when inreverse, flip brake and gas

      tmp=brake;

     brake=motor;

      motor=tmp;

      

      //whenmoving forward or standing and gas is pressed, switch to drive

     if((rev>0||flatVelo.sqrMagnitude<0.5)&&brake>0.1)

         gear=1;

   }

  engineForce=flatDir*CalcEngine();

  totalbrake=brake+handbrake*0.5;

  if(totalbrake>1.0)totalbrake=1.0;

  brakeForce=-flatVelo.normalized*totalbrake*rigidbody.mass*maxBrakeAccel;

  flatDir*=flatVelo.magnitude;

  flatDir=Quaternion.AngleAxis(steer*30.0,Vector3.up)*flatDir;

   flatDir*=rev;

  diff=(flatVelo-flatDir).magnitude;

  cornerAccel=maxCornerAccel;

  if(cornerAccel>diff)cornerAccel=diff;

  cornerForce=-(flatVelo-flatDir).normalized*cornerAccel*rigidbody.mass;

  cornerSlip=Mathf.Pow(cornerAccel/maxCornerAccel,3);

   

  rigidbody.AddForceAtPosition(brakeForce+engineForce+cornerForce,transform.position+transform.up*wheelY);

   

  handbrakeFactor=1+handbrake*4;

   if(rev<0)

     handbrakeFactor=1;

  veloSteer=((15/(2*velo.magnitude+1))+1)*handbrakeFactor;

  steerGrip=(1-handlingTendency*cornerSlip);

  if(rev*steer*steerVelo<0)

      steerGrip=1;

  maxRotSteer=2*Time.fixedDeltaTime*handbrakeFactor*steerGrip;

  fVelo=velo.magnitude;

  veloFactor=fVelo<1.0?fVelo:Mathf.Pow(velo.magnitude,0.3);

  steerVeloInput=rev*steer*veloFactor*0.5*Time.fixedDeltaTime*handbrakeFactor;

   if(velo.magnitude<0.1)

     steerVeloInput=0;

  if(steerVeloInput>steerVelo)

   {

     steerVelo+=0.02*Time.fixedDeltaTime*veloSteer;

     if(steerVeloInput<steerVelo)

        steerVelo=steerVeloInput;

   }

   else

   {

     steerVelo-=0.02*Time.fixedDeltaTime*veloSteer;

     if(steerVeloInput>steerVelo)

        steerVelo=steerVeloInput;

   }

  steerVelo=Mathf.Clamp(steerVelo,-maxRotSteer,maxRotSteer);   

  transform.Rotate(Vector3.up*steerVelo*57.295788);

}

function FixedUpdate () {

   //query inputaxes if necessarry

  if(queryUserInput)

   {

      brake =Mathf.Clamp01(-Input.GetAxis("Vertical"));

      handbrake= Input.GetButton("Jump")?1.0:0.0;

      steer =Input.GetAxis("Horizontal");

       motor =Mathf.Clamp01(Input.GetAxis("Vertical"));

    }

   else

   {

      motor = 0;

      steer = 0;

      brake = 0;

      handbrake= 0;

   }

 

   //if car ison ground calculate handling, otherwise just rev the engine

    if(onGround)

     HandlePhysics();

   else

     CalcEngine();   

      

   //wheel GFX

  UpdateWheels();

   //enginesounds

  audio.pitch=0.5+0.2*motor+0.8*engineRPM/maxRPM;

  audio.volume=0.5+0.8*motor+0.2*engineRPM/maxRPM;

}

//Called by DamageReceiver if boat destroyed

function Detonate()

{

   //destroywheels

   for( w inwheels )

     w.coll.gameObject.active=false;

   //no more carphysics

  enabled=false;

}

@script RequireComponent (Rigidbody)

@script RequireComponent (AudioSource)

0 0
原创粉丝点击