Last active
August 11, 2023 03:51
-
-
Save brihernandez/f92f666d0103e67392b0d88eb29db4f9 to your computer and use it in GitHub Desktop.
Freelancer ship physics for Unity. Includes engine kill and thruster.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==================================================================================================== | |
// In my codebase, all ships have their own instance of this that they use to apply physics with. | |
// I'm using a struct mostly because I want to maintain copy semantics. | |
// ==================================================================================================== | |
public struct FlightInput | |
{ | |
public float Pitch; | |
public float Yaw; | |
public float Roll; | |
public float Throttle; | |
public float StrafeHorizontal; | |
public float StrafeVertical; | |
public bool IsEngineKill; | |
public bool IsThrusterActive; | |
public bool IsReversing; | |
} | |
// ==================================================================================================== | |
// These are the member variables used for physics. The values here are taken from 88 Flak's Defender. | |
// In the actual Unity C# class, these are all properties that are exposed to the Inspector. | |
// ==================================================================================================== | |
// Physics | |
public float Mass = 150f; | |
public float LinearDrag = 155f; | |
public Vector3 AngularDrag = new Vector3(50000f, 50000f, 50000f); | |
public Vector3 AngularInertia = new Vector3(12500f, 12500f, 12500f); | |
public Vector3 SteeringTorque = new Vector3(120000f, 120000f, 120000f); | |
public float BankLimit = 80f; | |
// Engine | |
public float ThrustForce = 24000f; | |
public float BoosterForce = 12000f; | |
public float ReverseFraction = .5f; | |
public float StrafeForce = 18000f; | |
// ==================================================================================================== | |
// These functions are the core of Freelancer's physics. It's pretty straightforward since it uses | |
// linear drag for everything. The actual application of of the physics forces (thrust etc) are handled | |
// by Unity's Rigidbody, and all that math works out the same because physics is just physics. | |
// ==================================================================================================== | |
private void ConfigureRigidbody() | |
{ | |
Rigidbody = gameObject.AddComponent<Rigidbody>(); | |
Rigidbody.mass = Mass; | |
Rigidbody.useGravity = false; | |
Rigidbody.angularDrag = 0f; | |
Rigidbody.drag = 0f; | |
Rigidbody.inertiaTensor = AngularInertia; | |
Rigidbody.centerOfMass = Vector3.zero; | |
} | |
private void RunShipPhysics() | |
{ | |
// Ship thrust | |
if (GetIsEngineRunning()) | |
{ | |
var forwardThrustForce = FlightInput.IsReversing | |
? -ThrustForce * ReverseFraction | |
: ThrustForce * FlightInput.Throttle; | |
forwardThrustForce += FlightInput.IsThrusterActive ? BoosterForce : 0f; | |
var appliedLinearForce = new Vector3( | |
StrafeForce * FlightInput.StrafeHorizontal, | |
StrafeForce * FlightInput.StrafeVertical, | |
forwardThrustForce); | |
Rigidbody.AddRelativeForce(appliedLinearForce, ForceMode.Force); | |
// Linear drag forces | |
var dragForce = -Rigidbody.velocity * LinearDrag; | |
Rigidbody.AddForce(dragForce, ForceMode.Force); | |
} | |
// Ship rotation | |
var appliedAngularForce = new Vector3( | |
SteeringTorque.x * FlightInput.Pitch, | |
SteeringTorque.y * FlightInput.Yaw, | |
SteeringTorque.z * FlightInput.Roll); | |
Rigidbody.AddRelativeTorque(appliedAngularForce, ForceMode.Force); | |
// Angular drag forces | |
var localAngularVelocity = transform.InverseTransformVector(Rigidbody.angularVelocity); | |
var localAngularDragForce = Vector3.Scale(-localAngularVelocity, AngularDrag); | |
Rigidbody.AddRelativeTorque(localAngularDragForce, mode: ForceMode.Force); | |
} | |
public bool GetIsEngineRunning() | |
{ | |
return !FlightInput.IsEngineKill | |
|| FlightInput.IsThrusterActive | |
|| FlightInput.IsReversing | |
|| Mathf.Abs(FlightInput.StrafeHorizontal) > .1f | |
|| Mathf.Abs(FlightInput.StrafeVertical) > .1f; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment