94 lines
2.9 KiB
C#
94 lines
2.9 KiB
C#
using UnityEngine;
|
|
|
|
public class RCSController : MonoBehaviour
|
|
{
|
|
[Header("References")]
|
|
public Rigidbody rb;
|
|
public FuelTank fuelTank;
|
|
|
|
[Header("RCS Settings")]
|
|
public bool rcsEnabled = true;
|
|
public bool consumeFuel = true;
|
|
public float maxTorque = 2000f; // N*m
|
|
public float torqueResponseRate = 6000f; // N*m per second
|
|
public float leverArm = 2f; // meters
|
|
public float Isp = 250f; // seconds
|
|
public float inputDeadzone = 0.05f;
|
|
|
|
[Header("Input")]
|
|
public Vector3 controlInput; // x = yaw, y = pitch, z = roll (-1 to 1)
|
|
|
|
[Header("Output")]
|
|
public Vector3 appliedTorque = Vector3.zero; // world space
|
|
public float fuelFlowRate = 0f; // kg/s
|
|
|
|
private const float g0 = 9.80665f;
|
|
private Vector3 currentLocalTorque = Vector3.zero;
|
|
|
|
void FixedUpdate()
|
|
{
|
|
if (!rcsEnabled || rb == null)
|
|
{
|
|
appliedTorque = Vector3.zero;
|
|
currentLocalTorque = Vector3.zero;
|
|
fuelFlowRate = 0f;
|
|
return;
|
|
}
|
|
|
|
Vector3 clampedInput = new Vector3(
|
|
Mathf.Abs(controlInput.x) < inputDeadzone ? 0f : Mathf.Clamp(controlInput.x, -1f, 1f),
|
|
Mathf.Abs(controlInput.y) < inputDeadzone ? 0f : Mathf.Clamp(controlInput.y, -1f, 1f),
|
|
Mathf.Abs(controlInput.z) < inputDeadzone ? 0f : Mathf.Clamp(controlInput.z, -1f, 1f)
|
|
);
|
|
|
|
float pitchInput = clampedInput.y;
|
|
float yawInput = clampedInput.x;
|
|
float rollInput = clampedInput.z;
|
|
|
|
Vector3 targetLocalTorque = new Vector3(pitchInput, yawInput, rollInput) * maxTorque;
|
|
float maxDelta = torqueResponseRate * Time.fixedDeltaTime;
|
|
currentLocalTorque = Vector3.MoveTowards(currentLocalTorque, targetLocalTorque, maxDelta);
|
|
|
|
Vector3 fueledLocalTorque = ApplyFuelLimit(currentLocalTorque);
|
|
appliedTorque = rb.rotation * fueledLocalTorque;
|
|
}
|
|
|
|
private Vector3 ApplyFuelLimit(Vector3 desiredLocalTorque)
|
|
{
|
|
fuelFlowRate = 0f;
|
|
if (!consumeFuel || fuelTank == null)
|
|
{
|
|
return desiredLocalTorque;
|
|
}
|
|
|
|
if (leverArm <= 0f || Isp <= 0f)
|
|
{
|
|
return desiredLocalTorque;
|
|
}
|
|
|
|
float torqueMagnitude = desiredLocalTorque.magnitude;
|
|
if (torqueMagnitude <= 0f)
|
|
{
|
|
return Vector3.zero;
|
|
}
|
|
|
|
float requiredForce = torqueMagnitude / leverArm;
|
|
fuelFlowRate = requiredForce / (Isp * g0);
|
|
float fuelRequested = fuelFlowRate * Time.fixedDeltaTime;
|
|
float fuelProvided = fuelTank.RequestRcsFuel(fuelRequested);
|
|
|
|
if (fuelProvided < fuelRequested && fuelRequested > 0f)
|
|
{
|
|
float scale = Mathf.Clamp01(fuelProvided / fuelRequested);
|
|
return desiredLocalTorque * scale;
|
|
}
|
|
|
|
return desiredLocalTorque;
|
|
}
|
|
|
|
public void SetControlInput(Vector3 input)
|
|
{
|
|
controlInput = input;
|
|
}
|
|
}
|