Hi!
I am trying to apply hooke’s law to my box.
The problem here is that this “car” not remains in the ground, it starts jumping.
I set this values based on streetcars:
Mass: 1000
Suspension length: 1
Stiffness: 8000
This is my code:
void FixedUpdate()
{
RaycastHit hit;
for (int i = 0; i < wheelPoints.Length; i++)
{
var wheelPoint = wheelPoints[i];
if (Physics.Raycast(wheelPoint.transform.position,
-transform.up,
out hit,
suspensionLength,
layerMask))
{
// Spring force
float contactDepth = hit.distance - suspensionLength;
float springForce = - stiffness * contactDepth;
// Final force or suspension force
float suspensionForce = springForce;
rigidBody.AddForceAtPosition(transform.up * suspensionForce, wheelPoints[i].transform.position, ForceMode.Force);
vehicleInAir = false;
}
else
{
vehicleInAir = true;
}
}
}
Is there drag force somewhere? Drag and inefficiency in the spring are what prevent real springs from endlessly oscillating.
Nop, drag force is 0 and Angular Drag is 0.05.
Sorry, the screenshot that I added before is very small.
Edy
November 10, 2016, 12:57am
4
Easy. You are simulating springs without damper. An ideal spring alone just keeps oscillating forever. What you have there is a Harmonic Oscillator .
Real car suspensions have springs and dampers. Dampers are critical as they dissipate the oscillating energy in the spring allowing them to come to a rest pose. The damper can be implemented easily as a force that opposes the movement of the spring. Check out the mass–spring–damper example in the Wikipedia’s Damping article .
Edy:
Easy. You are simulating springs without damper. An ideal spring alone just keeps oscillating forever. What you have there is a Harmonic Oscillator .
Real car suspensions have springs and dampers. Dampers are critical as they dissipate the oscillating energy in the spring allowing them to come to a rest pose. The damper can be implemented easily as a force that opposes the movement of the spring. Check out the mass–spring–damper example in the Wikipedia’s Damping article .
Before I added the damper force, the car has been crazy but it is even worse now. I don’t know what am I doing wrong…
https://www.youtube.com/watch?v=iACL-2KlU18
Current values:
Mass: 1000
Suspension length: 1
Stiffness: 8000
damping: 800 // 10% of the stiffness
Current code:
void FixedUpdate()
{
RaycastHit hit;
for (int i = 0; i < wheelPoints.Length; i++)
{
var wheelPoint = wheelPoints[i];
if (Physics.Raycast(wheelPoint.transform.position,
-transform.up,
out hit,
suspensionLength,
layerMask))
{
// Spring force
float contactDepth = hit.distance - suspensionLength;
float springForce = - stiffness * contactDepth;
//Damper force
float compressionSpeed = contactDepth - lastContactDepth;
float damperForce = - damping * compressionSpeed;
// Final force or suspension force
float suspensionForce = springForce + damperForce;
rigidBody.AddForceAtPosition(transform.up * suspensionForce, wheelPoints[i].transform.position, ForceMode.Force);
vehicleInAir = false;
lastContactDepth = contactDepth;
}
else
{
vehicleInAir = true;
}
}
Edy
November 15, 2016, 12:45pm
6
1m is a large and unrealistic suspension.
For Mass=1000, I have a vehicle where these suspension settings work rather good:
Suspension length: 0.25
Spring rate: 25000
Damper rate: 1500
These are the settings at the WheelCollider. I’m not sure if/how they work implemented with direct forces.
Also note that in your code vehicleInAir depends on the latest evaluated wheel only, regardless all other wheels.
flatomic:
Before I added the damper force, the car has been crazy but it is even worse now. I don’t know what am I doing wrong…
https://www.youtube.com/watch?v=iACL-2KlU18
Current values:
Mass: 1000
Suspension length: 1
Stiffness: 8000
damping: 800 // 10% of the stiffness
Current code:
void FixedUpdate()
{
RaycastHit hit;
for (int i = 0; i < wheelPoints.Length; i++)
{
var wheelPoint = wheelPoints[i];
if (Physics.Raycast(wheelPoint.transform.position,
-transform.up,
out hit,
suspensionLength,
layerMask))
{
// Spring force
float contactDepth = hit.distance - suspensionLength;
float springForce = - stiffness * contactDepth;
//Damper force
float compressionSpeed = contactDepth - lastContactDepth;
float damperForce = - damping * compressionSpeed;
// Final force or suspension force
float suspensionForce = springForce + damperForce;
rigidBody.AddForceAtPosition(transform.up * suspensionForce, wheelPoints[i].transform.position, ForceMode.Force);
vehicleInAir = false;
lastContactDepth = contactDepth;
}
else
{
vehicleInAir = true;
}
}
Damper force is damping coefficient * speed
In your formula, I think compressionSpeed is not actually a speed, because you forgot dt
Try
float compressionSpeed = (contactDepth - lastContactDepth)/Time.deltaTime;
float damperForce = - damping * compressionSpeed;