Mapping movement to a WheelCollider suspension?

I'm in the process of building a car with a rather advanced graphical model, and I'm in a bit of a pickle:

How do I map the movement of my graphical wheels to that of the wheel-collider's suspension? I can think of a few ways to "hack it", but as far as I can see, the simplest and best way to deal with it would be to read the current compression rate of the spring in the wheel-collider, and map it straight to the wheels and suspension. Unfortunately, I can't actually find the variables or functions to read the current compression rate/distance in the WheelCollider, or its parents. Do they exist? This really would be the prettiest way, as the wheel-collider has to have the data somewhere, and it'll use a minimal amount of code and cpu load.

Alternate routes to take:

  • Go via GetGroundHit to get the WheelHit.point, and convert to local coordinates. ( Annoying, as when the WheelColliders leave the ground, the collisions stop, and for a jumping terrain vehicle I'd have to hardcode movement of the suspension when I'm airborn.

  • Create a seperate collider for the graphics, that will move the graphical suspension. ( I don't want to add colliders that aren't necessary though. Pointless CPU load.)


Edit. Apparently I can't make a comment. (Odd.)

I just found the car tutorial and it uses the WheelHit approach, which I suppose is all fine and dandy for some vehicles. Any time the wheels leave the ground, the wheels snap instantly into a "down position". For a 4x4 dune-buggy with >0.5 meter suspension - it's less than desireable. My vehicle doesn't rest on the ground in the fully extended spring position. Just gravity alone drops it .1 meter or more.

I also noticed that there doesn't seem to be any way to read the current state of any joints at all (that I can find anyway), which explains the messing around with WheelHit for the WheelColliders - and that strikes me as extremely odd. Any attempts to use joints seems to abandon me in the hands of physics. In most cases, I reckon that's a good thing - but not all. The wheelcollider is the perfect example.

I've also spent days on trimming the values for terrain physics material, suspension, springs, damping, friction values, engine power, etc, and I just never seem to get the results I want. For example, while the car is "pitching up" (starting to go up a slope), g-forces increase, your traction goes up, and the car accelerates, even beyond the car's top speed on a flat surface; this behaviour is a pain to get rid off! While I can see the logic behind the behaviour, going up a ramp or a loop should not increase a car's top speed. In my case, it's usually a matter of slamming the car into the lay-side of a sand dune, and I really hate it when my speed doubles in the blink of an eye, and launches my buggy like a ballistic missile into the sky.

Just top top it off, the rest-drift is really annoying. The car can barely sit still even on a flat surface. Even the smallest tilt of the ground makes the car drift sideways at close to 1 m/s, and it looks like you have to turn the vehicle Kinematic or something...

With the number of hacks it looks like I have to put into effect to get the WheelColliders to do what I want, I'm really beginning to wonder if they are worth the effort. Would it make my life easier to toss them, reinvent the wheel, and just do it myself?

You must calculate the position manually using Physics.Raycast, and you must do it from the Update method (not FixedUpdate).

var hit : RaycastHit;

if (Physics.Raycast(Wheel.transform.position, -Wheel.transform.up, hit, Wheel.suspensionDistance + Wheel.radius))
    WheelMesh.position = hit.point + Wheel.transform.up * Wheel.radius;
else
    WheelMesh.position = Wheel.transform.position - (Wheel.transform.up * WheelCol.suspensionDistance);

Here you can see the result: http://www.edy.es/unity/offroader_v2.html

The offroader gets closer to real behavior than most vehicles I have tested, but it's weak on acceleration, deceleration, and it sucks when it comes to steering. It either over-steers, under-steers, or drifts gripless. Sad, as the rest of its behavior appears good.

The first question is answered as constantly monitoring the Raycast will extend the suspension fully if not touching... a bit off when the vehicle is lying on its side for example.(see below)

The drift, I see is a problem in all demos...space bar handbrake does not work, it continues to drift.(WIN7 Pro, IE8).

The launching in the sky problem, I experience even when the vehicle is at a stand-still while slowly drifting(walk away from computer and poof it goes after a few secondfs or minutes).

. This is right out of the Untiy Scripting Reference. Take a look a the last 2 sentences. I am having a problem figuring that out.


In the Unity Script Ref:

var suspensionSpring : JointSpring

Description

The parameters of wheel's suspension. The suspension attempts to reach a target position

by adding spring and damping forces.

The suspensionSpring.spring force attempts to reach the target position. A larger value makes the suspension reach the target position faster.

The suspensionSpring.damper force dampens the suspension velocity. A larger value makes the suspension reach the goal slower.

The suspension tries to reach suspensionSpring.targetPosition, which is the rest length of the suspension along the suspensionDistance. Zero value maps to full extension along the suspension travel, a value of one maps to fully compressed suspension. Default value is zero, which matches the behavior of regular car's suspension.


Assuming the rest length is at about 85% of the total suspensionDistance(car weighing on the spring and compressing it a bit):

  1. the spring compressed to top of travel would be 1(wheel is as near fender well as allowed),
  2. the rest value would be .15(or .85)( <- I believe that is the targetPosition),
  3. and the full extension would be 0(as when the car is supported by a jack with wheel dangling, or even further extended if the car has lifted suddenly over a hard bump causing the wheel to snap away even further down).

.15,(.85) would be a default instead? am I getting this all wrong?

I do not see that 0 as the default is a match of a car's suspension, if 0=full extension.