I'm working on a sailing simulation in Unity3D. I have basic downwind sail physics implemented with sail angle and rudder control, but now I want to prevent "leeway", i.e. a ship's lateral movement. In a real ship, the daggerboard or keel provides a lot of resistance to sideways motion, which leads to the ship traveling more forward than sideways even with a wind from the side.
I currently have a GameManager object that calls a method on the ship to apply the wind physics in every FixedUpdate. There isn't an easy way to sum all the forces on the ship in a given frame, because each sail's force is applied with some offset according to where the sail is on the ship. So what I'm attempting to do is store the previous velocity of the ship, and in every FixedUpdate calculate how much the velocity has changed from the previous frame, and then apply an opposite acceleration to prevent leeway. Something like this:
Rigidbody rigidBody = this.ship.GetComponent<Rigidbody>();
// Get velocity in local coordinate frame
Vector3 localVelocity = rigidBody.transform.InverseTransformDirection(rigidBody.velocity);
float leewayDV = (localVelocity - this.previousVelocity).x;
this.previousVelocity = localVelocity;
Vector3 leewayCorrection = -1.0f * leewayDV * rigidBody.transform.right;
leewayCorrection = rigidBody.transform.TransformDirection(leewayCorrection);
rigidBody.AddForce(leewayCorrection, ForceMode.Acceleration);
(Ultimately, the leeway correction won't be 100%, but I'm using 100% while debugging).
Debugging code is showing that I'm applying an acceleration to try to prevent this motion, but it's not working as intended. I don't know if there's something fundamentally wrong with this approach, or a bug in my implementation, or if there's just an entirely different way that I could accomplish this.