Merge pull request #30685 from jonri/vehicle-per-wheel-forces

Vehicle per-wheel forces
This commit is contained in:
Rémi Verschelde 2019-07-25 11:45:22 +02:00 committed by GitHub
commit ffc8fb9c48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 11 deletions

View File

@ -13,6 +13,7 @@
<return type="float">
</return>
<description>
Returns the rotational speed of the wheel in revolutions per minute.
</description>
</method>
<method name="get_skidinfo" qualifiers="const">
@ -31,12 +32,23 @@
</method>
</methods>
<members>
<member name="brake" type="float" setter="set_brake" getter="get_brake" default="0.0">
Slows down the wheel by applying a braking force. The wheel is only slowed down if it is in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidBody.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking.
</member>
<member name="damping_compression" type="float" setter="set_damping_compression" getter="get_damping_compression" default="0.83">
The damping applied to the spring when the spring is being compressed. This value should be between 0.0 (no damping) and 1.0. A value of 0.0 means the car will keep bouncing as the spring keeps its energy. A good value for this is around 0.3 for a normal car, 0.5 for a race car.
</member>
<member name="damping_relaxation" type="float" setter="set_damping_relaxation" getter="get_damping_relaxation" default="0.88">
The damping applied to the spring when relaxing. This value should be between 0.0 (no damping) and 1.0. This value should always be slightly higher than the [member damping_compression] property. For a [member damping_compression] value of 0.3, try a relaxation value of 0.5.
</member>
<member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force" default="0.0">
Accelerates the wheel by applying an engine force. The wheel is only speed up if it is in contact with a surface. The [member RigidBody.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration.
[b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears.
A negative value will result in the wheel reversing.
</member>
<member name="steering" type="float" setter="set_steering" getter="get_steering" default="0.0">
The steering angle for the wheel. Setting this to a non-zero value will result in the vehicle turning when it's moving.
</member>
<member name="suspension_max_force" type="float" setter="set_suspension_max_force" getter="get_suspension_max_force" default="6000.0">
The maximum force the spring can resist. This value should be higher than a quarter of the [member RigidBody.mass] of the [VehicleBody] or the spring will not carry the weight of the vehicle. Good results are often obtained by a value that is about 3× to 4× this number.
</member>
@ -47,10 +59,10 @@
This is the distance the suspension can travel. As Godot units are equivalent to meters, keep this setting relatively low. Try a value between 0.1 and 0.3 depending on the type of car.
</member>
<member name="use_as_steering" type="bool" setter="set_use_as_steering" getter="is_used_as_steering" default="false">
If [code]true[/code], this wheel will be turned when the car steers.
If [code]true[/code], this wheel will be turned when the car steers. This value is used in conjunction with [member VehicleBody.steering] and ignored if you are using the per-wheel [member steering] value instead.
</member>
<member name="use_as_traction" type="bool" setter="set_use_as_traction" getter="is_used_as_traction" default="false">
If [code]true[/code], this wheel transfers engine force to the ground to propel the vehicle forward.
If [code]true[/code], this wheel transfers engine force to the ground to propel the vehicle forward. This value is used in conjunction with [member VehicleBody.engine_force] and ignored if you are using the per-wheel [member engine_force] value instead.
</member>
<member name="wheel_friction_slip" type="float" setter="set_friction_slip" getter="get_friction_slip" default="10.5">
This determines how much grip this wheel has. It is combined with the friction setting of the surface the wheel is in contact with. 0.0 means no grip, 1.0 is normal grip. For a drift car setup, try setting the grip of the rear wheels slightly lower than the front wheels, or use a lower value to simulate tire wear.

View File

@ -272,6 +272,20 @@ void VehicleWheel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rpm"), &VehicleWheel::get_rpm);
ClassDB::bind_method(D_METHOD("set_engine_force", "engine_force"), &VehicleWheel::set_engine_force);
ClassDB::bind_method(D_METHOD("get_engine_force"), &VehicleWheel::get_engine_force);
ClassDB::bind_method(D_METHOD("set_brake", "brake"), &VehicleWheel::set_brake);
ClassDB::bind_method(D_METHOD("get_brake"), &VehicleWheel::get_brake);
ClassDB::bind_method(D_METHOD("set_steering", "steering"), &VehicleWheel::set_steering);
ClassDB::bind_method(D_METHOD("get_steering"), &VehicleWheel::get_steering);
ADD_GROUP("Per-Wheel Motion", "");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "engine_force", PROPERTY_HINT_RANGE, "0.00,1024.0,0.01,or_greater"), "set_engine_force", "get_engine_force");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "brake", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_brake", "get_brake");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "steering", PROPERTY_HINT_RANGE, "-180,180.0,0.01"), "set_steering", "get_steering");
ADD_GROUP("VehicleBody Motion", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_traction"), "set_use_as_traction", "is_used_as_traction");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_steering"), "set_use_as_steering", "is_used_as_steering");
ADD_GROUP("Wheel", "wheel_");
@ -288,6 +302,34 @@ void VehicleWheel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "damping_relaxation"), "set_damping_relaxation", "get_damping_relaxation");
}
void VehicleWheel::set_engine_force(float p_engine_force) {
m_engineForce = p_engine_force;
}
float VehicleWheel::get_engine_force() const {
return m_engineForce;
}
void VehicleWheel::set_brake(float p_brake) {
m_brake = p_brake;
}
float VehicleWheel::get_brake() const {
return m_brake;
}
void VehicleWheel::set_steering(float p_steering) {
m_steering = p_steering;
}
float VehicleWheel::get_steering() const {
return m_steering;
}
void VehicleWheel::set_use_as_traction(bool p_enable) {
engine_traction = p_enable;
@ -374,10 +416,7 @@ void VehicleBody::_update_wheel(int p_idx, PhysicsDirectBodyState *s) {
Vector3 fwd = up.cross(right);
fwd = fwd.normalized();
//rotate around steering over de wheelAxleWS
real_t steering = wheel.steers ? m_steeringValue : 0.0;
Basis steeringMat(up, steering);
Basis steeringMat(up, wheel.m_steering);
Basis rotatingMat(right, wheel.m_rotation);
@ -723,12 +762,11 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) {
real_t rollingFriction = 0.f;
if (wheelInfo.m_raycastInfo.m_isInContact) {
if (engine_force != 0.f && wheelInfo.engine_traction) {
rollingFriction = -engine_force * s->get_step();
if (wheelInfo.m_engineForce != 0.f) {
rollingFriction = -wheelInfo.m_engineForce * s->get_step();
} else {
real_t defaultRollingFrictionImpulse = 0.f;
float cbrake = MAX(wheelInfo.m_brake, brake);
real_t maxImpulse = cbrake ? cbrake : defaultRollingFrictionImpulse;
real_t maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
btVehicleWheelContactPoint contactPt(s, wheelInfo.m_raycastInfo.m_groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, m_forwardWS[wheel], maxImpulse);
rollingFriction = _calc_rolling_friction(contactPt);
}
@ -886,6 +924,11 @@ void VehicleBody::_direct_state_changed(Object *p_state) {
void VehicleBody::set_engine_force(float p_engine_force) {
engine_force = p_engine_force;
for (int i = 0; i < wheels.size(); i++) {
VehicleWheel &wheelInfo = *wheels[i];
if (wheelInfo.engine_traction)
wheelInfo.m_engineForce = p_engine_force;
}
}
float VehicleBody::get_engine_force() const {
@ -896,6 +939,10 @@ float VehicleBody::get_engine_force() const {
void VehicleBody::set_brake(float p_brake) {
brake = p_brake;
for (int i = 0; i < wheels.size(); i++) {
VehicleWheel &wheelInfo = *wheels[i];
wheelInfo.m_brake = p_brake;
}
}
float VehicleBody::get_brake() const {
@ -905,6 +952,11 @@ float VehicleBody::get_brake() const {
void VehicleBody::set_steering(float p_steering) {
m_steeringValue = p_steering;
for (int i = 0; i < wheels.size(); i++) {
VehicleWheel &wheelInfo = *wheels[i];
if (wheelInfo.steers)
wheelInfo.m_steering = p_steering;
}
}
float VehicleBody::get_steering() const {

View File

@ -70,7 +70,7 @@ class VehicleWheel : public Spatial {
real_t m_deltaRotation;
real_t m_rpm;
real_t m_rollInfluence;
//real_t m_engineForce;
real_t m_engineForce;
real_t m_brake;
real_t m_clippedInvContactDotSuspension;
@ -137,6 +137,15 @@ public:
float get_rpm() const;
void set_engine_force(float p_engine_force);
float get_engine_force() const;
void set_brake(float p_brake);
float get_brake() const;
void set_steering(float p_steering);
float get_steering() const;
String get_configuration_warning() const;
VehicleWheel();