Dedicated to racing PerformanceAlgorithmWhen the final version of a racing car is determined for a long time, let's make a summary.
ArticleStill not very detailed, point to point, do not think too much use of work time.
Before making a vehicle, you must first understand the principle of the real vehicle:
The vehicle is divided into front-wheel drive, rear-wheel drive and four-wheel drive. Power SupplyEngineProvide, the reaction force to the tire, thus generating the number of turns, that is, rpm.
The engine power can be obtained by the RPM formula: rpm = engine power × 60/2 × Pi, which are simulated to better serve the following actions. There is also a "drift" of public interest. The so-called "drift" means that in the rear drive vehicles, the front wheel rotates at a large angle, and the ground gives a certain centripetal force while the rear wheel gives more power, this causes the "drift" action.
Based on the above principles, it is easier to understand the following article.
I would like to explain that there are many waysDevelopmentA racing car. After numerous methods and numerous revisions, I finally chose a public version. These methods can be used one by one.
First of all, you need to understand that a vehicle cannot be built with a whole casing, because when you are in contact with the ground, the force on the vehicle cannot reach your expected goal, A shell collision must be performed on a vehicle tire or above, and the following must be powerful to support it and keep it from falling.
Unity3d has a magical thing calledThe wheelcollider is designed to simulate the tire support force and tire rotation, as well as the tire lateral force, forward force, and Suspension Shock Absorber System.
This is very convenient, as long as you put this thing on four tires, debug hisForwardfriction andSidewaysfriction
To achieve the desired effect, and then to the drive wheelMotortorque is assigned a value, so your vehicle can act.
Remember that you need to debug the forward and lateral friction countless times. As for the suspension system, you can change its value as needed. Also, the two friction forces are a curve from low to high, and then from high to stable.
This wheelcollider was very useful and once indulged in it. But later I found that he had a lot of unreasonable points. If you want the best effect, you can discard it.
In order to support the collision shell of a vehicle without touching the ground, a dynamic support force of the suspension must be written. In the four tire positions, the whole vehicle can be suspended on the ground.
The dynamic support of this suspension is provided here:
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. col Lider. 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, grou Ndnormal) * 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 (GA Meobject 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. posi Tion,-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 ;}}}
After completing the suspension support, we should design the vehicle power.
There are also two ways: one is the real vehicle trajectory and the other is the simulated vehicle trajectory.
The former method is to place the Power Point on the driving wheel of the vehicle, such as the rear wheel. Using RigidbodyAddforceatposition can be achieved, and the front wheel only needs to provide the horizontal force to achieve the turning trajectory. But let's not look at it so easily. It involves a lot of numerical and curve problems. When providing vehicle power, you need a curve so that the vehicle will not speed up smoothly, because this is not true, and in the front wheel lateral force, you must be from 0 to the highest point, then the curve drops to the equilibrium point. In this way, your racing car will become more authentic. These require a few mathematical knowledge.
The latter is a vehicle track simulated by an algorithm. All the force of this algorithm is applied to the center of the vehicle.
The turning track is represented by the turning radius, so that the vehicle has a considerable degree of authenticity during the turning, and the turning speed must be changed. Of course, I used some mathematical knowledge.CodeDedication:
# Region calculates the turning angle 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. magn0000* 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. magnspeed); 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 debustartpoint = transform. Position + transform. Right * turnradius * This. steeringinput ;//~ Vector3 debugendpoint = debustartpoint + vector3.up * 5f ;//~ Debug. drawline (debustartpoint, 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
This simulated vehicle trajectory cannot achieve the drifting performance, but I added a moving ratio calculation algorithm to determine the ratio of the vehicle's horizontal movement speed to the forward speed, whether the vehicle is in the drifting status. If the vehicle is in the drifting status, the drifting slide is started.Program. Of course, my racing car is quite natural and I don't want to do it. As for the tire trace, the gameobject of the tire trace is generated at this point after determining whether to touch the bottom.
Finally, I would like to introduce the things that all vehicles need to simulate. When driving, the tires rotate with speed, which is related to the authenticity of the vehicle. It is actually very simple. Not to mention, send the Code:
# Region Tire Rolling and rotating simulation void wheelroll () {float averageangularvelo = (this. rigidbody. getpointvelocity (this. bwheelmodels [0]. transform. parent. position ). magnpipeline + this. rigidbody. getpointvelocity (this. bwheelmodels [0]. transform. parent. position ). magnregular)/2f; float engineangularvelo = averageangularvelo * 3f; float RPM = engineangularvelo * (601_f/(2 * mathf. pi) * (this. transform. inversetransformdirection (T His. 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); // rotate fwheelmodels [1]. transform. rotation = fwheelmodels [1]. transform. parent. rotation * Quaternion. euler (rotationvalue, this. steering, 0); // rotate bwheelmodels [0]. transform. rotation = bwheelmodels [0]. transform. parent. rotation * Quaternion. euler (rotationvalue, 0, 0); // rotate bwheelmodels [1]. transform. rotation = bwheelmodels [1]. transform. parent. rotation * Quaternion. euler (rotationvalue, 0, 0); // rotate rotationvalue + = RPM * (360f/60f) * time. deltatime ;}# endregion