For the linear component:
The PointOnPlaneJoint would work. Just make connection A null so that the plane is attached to the world space rather than another entity.
A cheaper option would be to always set the y component of the tank's linear velocity to 0 and then set the position directly to be exactly where you want. Changing the position is nonphysical, but so long as the teleportation distance isn't too significant, it generally still works okay. Setting the y velocity to 0 avoids most divergence.
For the angular component:
To absolutely lock orientation to be yaw only, you could set the first and third rows of the entity.LocalInertiaTensorInverse to 0, like so:
Code: Select all
var locked = entity.LocalInertiaTensorInverse;
locked.Right = new Vector3();
locked.Forward = new Vector3();
entity.LocalInertiaTensorInverse = locked;
That effectively makes the inertia around those two local axes infinite, which means no dynamic force can make the angular velocity change around those local axes.
For a softer approach, you could use a SwingLimit. You can then configure the SwingLimit's softness to your liking. There's also the option of just changing the angular velocity when the entity's up vector diverges from world up. That would be cheaper than a full constraint.
For a convex hull's half height, you could take the ConvexHullShape and call its GetBoundingBox, or call GetLocalExtremePoint along (0,1,0) and (0,-1,0).