Open MrMinimal opened 3 years ago
Once confirmed, worth to mention it in https://github.com/godotengine/godot/issues/45333
Confirmed in 3.2.3 stable and 3.2.4 beta 6.
Bullet: wheels sink into the ground as described. Godot Physics: the truck doesn't move forward.
Isn't limited to the truck, btw - a standard 4 wheel car also has the wheels partly sinking - I thought it was just a graphical glitch until I saw this report.
I can confirm this issue on Godot 3.3.4. This especially happens when a vehicle collides very fast with a collision shape. For example an airplane: On ground the wheels are above the ground perfectly, but at landing (with fast movement) the wheels go below the ground on touch down (and stay there). is_in_contact()
returns false and the aircraft sinks to ground so that only the collision body is visible.
Also present in Godot 3.4.
So, I previously thought this was an issue with the engine in 3.4 (currently using), but I think it may be the documentation that is incorrect on how to use it, and the default values may just not be relevant to the example project mentioned.
The answer to this question( https://godotengine.org/qa/83746/confusion-about-vehiclebody ) helped me solve my issues with not understanding how the wheels actually worked, and the clipping I experienced went away.
They suggest watching this video (https://www.youtube.com/watch?v=B5vE-nNszxA) where the settings are explained a bit more in detail. In particular it's noted that the 'y-value' of the wheel transform should be equal to the 'rest_length' to compensate for the fact that the center of the wheel is actually where the spring mounts to the vehicle, so the visual representation of the spring being drawn upwards is somewhat confusing as rest_length increases.
some other things which were an issue was too low of settings for max force, and travel being way too high (should be equal or lower than rest_length). And increasing stiffness helped the movement feel more smooth.
I suggest the documentation be looked into being made clearer. When I have time I'll try to look into how I might contribute to that, but if someone tackles it before me, grazie.
Whoa, thanks for saying that y of wheel should be equal to rest_length - I was one of the people mislead by the visual spring...
@qaptoR @Zireael07 I'm trying to replicate this but am not successful with it. Do you have an example project to share? Then I can apply the fix the Truck Town demo.
I don't have a minimal project, unfortunately. I think the issue went away at some point, or became so unnoticeable that I just don't notice it
Also present in Godot 3.4.
Also present in Godot 4.0.alpha.custom_build.950750fb9 (https://github.com/godotengine/godot-demo-projects/tree/5566c748c210e9ca47baa77b7bdc9ba95e7b2f58/3d/truck_town)
Another more minimal MRP from #65739:
Makes me wonder:
If the rest_length
and the wheel's y
value should always be equal, then what's the point of having to set both? It's unwieldy and error prone. Either the implementation should infer the rest_length
from the y
, or the rest_length
should work on its own regardless of the y
.
Unless I'm missing something...
(EDIT: actually it seems to me that you can never have raised suspensions if you make rest_length
equal to y
. I tested it in Godot 4, though.)
Also, according to @BastiaanOlij, the suspension travel
shouldn't be higher than the rest_length
, so wouldn't it be easier to work with if the travel
was a percentage instead?
As it is, changing the rest_length
always requires that you also change two other values, which isn't ideal, in my opinion.
As I had the same Issue, I looked into the Code. It seems like the spring length is being calculated incorrectly. I made an own issue, as I originally thought this was just a visual glitch.
I just noticed the already existing fix for this. Please merge.
The original btRaycastVehicle
https://github.com/bulletphysics/bullet3/blob/6bb8d1123d8a55d407b19fd3357c724d0f5c9d3c/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp#L160 from Bullet does a raycast from the wheel's world position down to a point of distance raylen = suspension_rest_length + wheel_radius
below the wheel. When the ray hits a point at distance hit_distance
from its starting point, it makes sense to set suspension_length = hit_distance - wheel_radius
. The PR https://github.com/godotengine/godot/pull/47412 restores that behavior from Bullet. It also simplifies the calculation of hit_distance
and makes it a bit more precise, under the restriction in Godot that the raycast doesn't return the value of the line parameter param
(the number between 0.0
and 1.0
that indicates where the raycast hit occurred), which was calculated manually instead. (In fact with this approach the whole param
and depth
variables can be removed and the method can be made to return void
as the return value is never used.)
Now, the vehicle body code in Godot was changed 10 years ago in 1a2cb75
(around Godot 1.0) to move the starting point of the raycast up to a point of distance wheel_radius
above the wheel (and keeping the endpoint the same as before, so increasing the length of the ray). My guess is that this was done to fix issues like what @Calinou reports in https://github.com/godotengine/godot/pull/47412#pullrequestreview-1910032892. The issue with that fix was that suspension_length
is then computed incorrectly, as the meaning of hit_distance
changed. To keep the hit_distance
relative to the wheel's world position, it should be e.g. (as the only change on top of master
):
diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp
index c23032d3b9..36e428c648 100644
--- a/scene/3d/vehicle_body_3d.cpp
+++ b/scene/3d/vehicle_body_3d.cpp
@@ -425,7 +425,7 @@ real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState3D *s) {
wheel.m_raycastInfo.m_groundObject = Object::cast_to<PhysicsBody3D>(rr.collider);
}
- real_t hitDistance = param * raylen;
+ real_t hitDistance = param * (raylen + wheel.m_wheelRadius) - wheel.m_wheelRadius;
wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelRadius;
//clamp on max suspension travel
The difference is param * wheel_radius - wheel_radius = (param - 1.0) * wheel_radius
. This is small when param
is close to 1.0
(which was also made more likely by moving the ray up and increasing its length), but often visibly nonzero as in this issue. The patch above combines "move the ray up" (already in master
) and "calculate the hit distance correctly", whereas https://github.com/godotengine/godot/pull/47412 undoes "move the ray up" but does "calculate the hit distance correctly".
The problem (probably) with the above patch is that hit_distance
can be negative, which may cause weird physics behavior (maybe worth testing).
To resolve this issue I think somebody should look at how some popular implementation of a car with raycasts solves this problem, and implement it in Godot.
how some popular implementation of a car with raycasts solves this problem, and implement it in Godot.
Other than Bullet, I think you mean, as Godot's implementation is pretty much Bullet's...
Jolt has a pretty complete vehicle implementation which also has more features (such as gears and RPM), but it'll need to be moved to core so it can be plugged in VehicleBody/VehicleWheel effectively. We could technically have properties that have no effect when using GodotPhysics, but it's not ideal to have properties that have no effect until you install an extension (e.g. VideoStreamPlayer seeking).
Godot version: 3.2.3-stable
OS/device including version: Linux
Issue description: Anytime I use VehicleWheel, it sinks into the ground as seen here:![image](https://user-images.githubusercontent.com/8739690/105231559-5e7de480-5b67-11eb-80cd-501eb6f260f9.png)
The wheel is made to fit the mesh like so:![image](https://user-images.githubusercontent.com/8739690/105231698-8e2cec80-5b67-11eb-994c-5f196efb7953.png)
Steps to reproduce:
Minimal reproduction project: Truck town has it all over: https://github.com/godotengine/godot-demo-projects/tree/master/3d/truck_town