- Home /
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?
$$anonymous$$ost highly tuned race games alter physics settings on the fly, mainly cos game physics is not very realistic. Check out the unity car tutorial to see how friction and centre of mass are altered constantly
Answer by Edy · Aug 16, 2010 at 05:50 PM
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
...can you explain why from the Update versus the FixedUpdate? I think I read in the manual that it should be in the FixedUpdate...???
Visuals should be in Update because they should be updated on each visual frame rendered. Physics gets updated on each fixed time step (each 0.02 ms by default), but the object keeps moving on each frame rendered ($$anonymous$$. 60 fps, variable rate). Using FixedUpdate for calculating the Wheel's positions means that you'll find them to intersect with the ground in a weird fashion. For instance, they may be effectively grounded but the physics hasn't detected the contact yet (will do at the next FixedUpdate), so the wheel will appear penetrating the ground.
@Edy:
Can you explain a little what the Wheel, Wheel$$anonymous$$esh and WheelCol vars truely are? I'm assu$$anonymous$$g the mesh is the visual 'wheel' 3d object, the wheelcol is the wheel collider. But what is the Wheel? Is it an empty game object that encompases the wheelmesh?
Currently i'm using this code to calc the movement of the wheels in my test vehicle. However the issue I'm trying to work out is when the raycast doesn't hit, the wheels seem to go to about a 45 degree angle or sometimes they are just sucked up into the wheel wells really far (after going off a large jump). So what I'm trying to make is that they go to a full suspension position and stay there until the raycast hits.
This is why I was hoping you could explain a little further each var so I can get a better idea of what you are truely doing.
-Thanks!
Is there a correctly syntaxed version of this script? for examples what's happening here: Wheel.transform.up WheelCol.suspensionDistance
?
Answer by dingben · Sep 19, 2010 at 10:08 AM
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):
- the spring compressed to top of travel would be 1(wheel is as near fender well as allowed),
- the rest value would be .15(or .85)( <- I believe that is the targetPosition),
- 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.
I voted Edy's answer up as it resolves part of the issue... gettign the wheel to follow the wheelcollider... should it not check fo the center position of the collider as collider's and wheels tend to 'rubberband' out of position?
targetPosition must be zero. Otherwise, the wheel tries to go upwards ins$$anonymous$$d of downwards in the last (lower) portion of the suspension travel, making that portion ineffective as car suspension.
Your answer
Follow this Question
Related Questions
Car - WheelCollider - Why the side is getting up? 2 Answers
Best wheel collider values (forward friction,sidewards friction) for racing cars ? 1 Answer
How to translate car wheels to suspension? 1 Answer
How is wheelCollider RPM calculated exactly? 1 Answer
Pushing a cart with a vehicle (Not generating initial torque) 0 Answers