I want to emulate car physics without using the VehicleBody node. I want to connect 5 rigid bodies consisting of one main body and 4 wheels yet I don't know how to fasten the relative position of each RigidBody with respect to each other.
Is there a way to connect multiple rigid bodies to emulate car physics?
Would setting the PinJoint's bias and damping to INF be the proper solution here?
DaveTheCoder
I tried PinJoint. It didn't work. Can you help?
download godot project
Note theres also the Generic6DOFJoint to try and other joint types too. Also all the Joints extend the Joint baseclass. Perhaps HingeJoint would be best for wheels?
- Edited
Xtreme_93
Could you re-upload that as a .zip, without the .import folder?
Please explain what the project is doing when it's run.
DaveTheCoder
This is a project file I try different things to learn godot. You need to look at the scene main3d2 for the car test. When I drop the car object, its wheels come apart which I don't want.
- Edited
I know it's been a while, but hopefully I can still be of some help. I think the way I'd recommend the most is something like AshDev's method which is using Unity's equivalent of Godot's Generic6DOFJoints
, and applying forces to the car body. In his method, the wheels just tag along, they don't have any effect on the car, and the joints do the suspensions and steering (not the force, just the visual wheel rotation). But if you need finer control, you can always have the wheels actually affect the car instead.
I did something like that, but since I was having trouble with math and physics, I started out with SaitoDePaula's method, which also uses Generic6DOFJoints
(github link in the video -- godot 3). But he relies on the joint's rotation (x angular motion) to propel the car, and it's a bit too slippery, like you're always on ice, so I added forces to the car on top of it, based on AshDev's method. This made the car a lot more responsive. Then I had each wheel calculate the forces it should apply to the car, partially based on this video, but also other sources. In my case I also decided to complicate it even further, and use the _integrate_forces function to calculate the contact points of the wheels, and apply forces based on those points (requires turning on "contact reporting" in the inspector, for the wheel's rigidbody node).
The problem with this method is I still find it a bit hard to control how cars should behave, and I had lots of trouble adapting the whole thing to a totally different car. I started out with a monster-truck and then went to a stock-car, and it didn't go well at all. I'm not sure it's the system being bad, or just me being inexperienced, because it seems to me cars are also difficult to get right in general.
If you can handle the math to get it working, I still recommend you use the joints solely for the suspensions and steering, like AshDev does. Lock everything else, and use only Y movement for springs and Y rotation for steering. Or you can calculate the suspensions on your own if you want (I think, I'm not sure), as you'll have finer control. And instead of rotating the joints, you can rotate the wheel meshes according to movement, like AshDev does. If you need finer control of that, you can also calculate traction and all that good stuff, which is explained in some detail in these articles, and there are some other useful resources listed there too that can help.
My inability to understand all that complicated stuff is also the reason I chose to mix those methods. I didn't know how to rotate the wheels in a more believable way, so I had the joints do it for me.
An important thing to keep in mind: wheels must have a PhysicsMaterial
on them (on the RigidBody node), and if you go the AshDev's route, then you must set its friction and roughness to zero, because you'll be applying all the forces yourself, and you don't want the physics engine to be applying any unwanted friction.
This is what my car scene looks like. This is for both methods. (I'm using Jolt physics in Godot 4, so the joints are from jolt's.)
The placement of the joints in the scene is whatever you want. I have them as children of the wheels just because I'm experimenting with including them in the wheel scenes, but you can have them as siblings if you want, as in:
car
car_body
wheel1
wheel2
etc...
joint1
joint2
etc...
All that matters is that you set the two nodes that the joint is supposed to hold in the inspector.
The wheels are simply what you might expect:
Jolt joints are a bit different from Godot's joints. While my truck needed well over 100000 stiffness
and 800 damping
in the "linear spring" using Godot's joints, now it only needs 3 frequency
(instead of stiffness, apparently) and 0.8 damping
. Also, jolt joints have an extra "linear limit spring", which seems to do nothing, but can be confused with "liner spring", which is the one you need for suspensions.
The other optional ingredient for suspensions is the "linear_limit". You can use it to set how far the suspension can travel. It's probably better to limit it, so the suspensions can't compress so much that the wheels go through the car body, and that sort of thing.
Also, important thing about turning the wheels, you have to leave the joint's Y angular limit enabled at all times, and when applying steering you change the limit values. If you don't limit angular Y, the wheels will be flapping around weirdly. My steering function looks like this (it's in the wheels, in my case):
func do_steering(steer_value):
if not use_as_steering: return
var steer_value_rads := deg_to_rad(steer_value)
_joint.set("angular_limit_y/lower", steer_value_rads)
_joint.set("angular_limit_y/upper", steer_value_rads)
(The steer_value
in my case is not the input value, but an interpolated value, so that the wheels gradually turn toward the maximum steering angle, instead of abruptly.)