196 lines
6.8 KiB
C#
196 lines
6.8 KiB
C#
using UnityEngine;
|
|
|
|
public class MainEngine : MonoBehaviour
|
|
{
|
|
[Header("References")]
|
|
public FuelTank fuelTank; // Reference to the fuel tank supplying this engine
|
|
public Altimeter altimeter; // Reference to the altimeter for gravity calculations
|
|
|
|
[Header("Engine Settings")]
|
|
public float maxThrust = 1000f; // kN
|
|
public float Isp = 300f; // seconds
|
|
public float throttleRampTime = 2f; // seconds to reach full throttle
|
|
public float minStartupFlow = 0.05f; // minimum fraction of max flow to maintain ignition
|
|
public AnimationCurve throttleCurve = AnimationCurve.Linear(0, 0, 1, 1);
|
|
|
|
[Header("Efficiency Settings")]
|
|
[Range(0f, 1f)] public float engineEfficiency = 1f; // e.g., reduce if engine is hot or damaged
|
|
|
|
[Header("Engine Status")]
|
|
public bool engineOnline = false; // true if engine is running
|
|
public bool engineIgnited = false; // true if ignition completed
|
|
public bool restartable = true; // if false, engine cannot restart once shut down
|
|
[Range(0f, 1f)]public float throttleInput = 0f; // 0-1 input from pilot
|
|
public float thrust = 0f; // kN
|
|
public float fuelFlowRate = 0f; // kg/s
|
|
|
|
private float effectiveThrottle = 0f; // ramped throttle for smooth startup/shutdown
|
|
private float startupTimer = 0f;
|
|
private bool everStarted = false; // tracks if engine has ever been started
|
|
private float postIgnitionTimer = 0f; // timer for post-ignition grace period
|
|
private const float postIgnitionGrace = 0.5f; // seconds to allow ramp-up after ignition
|
|
private float g = 9.81f; // local gravity from altimeter
|
|
|
|
void Update()
|
|
{
|
|
HandleEngineState();
|
|
UpdateThrottle();
|
|
// Only calculate thrust and fuel flow if engine is ignited
|
|
if (engineOnline && engineIgnited)
|
|
{
|
|
// Update post-ignition timer
|
|
if (postIgnitionTimer < postIgnitionGrace)
|
|
postIgnitionTimer += Time.deltaTime;
|
|
CalculateThrustAndFuelFlow();
|
|
}
|
|
else
|
|
{
|
|
thrust = 0f;
|
|
fuelFlowRate = 0f;
|
|
postIgnitionTimer = 0f;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles startup, shutdown, and engine cutout.
|
|
/// </summary>
|
|
private void HandleEngineState()
|
|
{
|
|
g = (float)altimeter.gh; // Update local gravity from altimeter each frame
|
|
|
|
// Check if engine is offline and restartable conditions
|
|
|
|
if (!engineOnline)
|
|
{
|
|
effectiveThrottle = Mathf.MoveTowards(effectiveThrottle, 0f, Time.deltaTime / throttleRampTime);
|
|
thrust = 0f;
|
|
fuelFlowRate = 0f;
|
|
|
|
// Mark engine as having been started
|
|
if (engineIgnited) everStarted = true;
|
|
|
|
if (engineIgnited)
|
|
Debug.Log("[MainEngine] Engine shutdown: engineOnline set to false.");
|
|
engineIgnited = false;
|
|
return;
|
|
}
|
|
|
|
// Prevent restart if engine is not restartable and was previously started
|
|
if (!restartable && everStarted)
|
|
{
|
|
Debug.Log("[MainEngine] Engine shutdown: not restartable and already started.");
|
|
engineOnline = false;
|
|
effectiveThrottle = 0f;
|
|
thrust = 0f;
|
|
fuelFlowRate = 0f;
|
|
engineIgnited = false;
|
|
return;
|
|
}
|
|
|
|
// Engine is commanded online
|
|
if (!engineIgnited)
|
|
{
|
|
// Startup delay / ignition sequence
|
|
startupTimer += Time.deltaTime;
|
|
if (startupTimer >= throttleRampTime)
|
|
{
|
|
engineIgnited = true;
|
|
startupTimer = 0f;
|
|
postIgnitionTimer = 0f; // reset grace period timer
|
|
Debug.Log("[MainEngine] Engine ignition complete.");
|
|
}
|
|
else
|
|
{
|
|
// Slowly ramp effective throttle during startup
|
|
effectiveThrottle = Mathf.Lerp(0f, throttleInput, startupTimer / throttleRampTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Smooths throttle input over time (fuel ramping)
|
|
/// </summary>
|
|
private void UpdateThrottle()
|
|
{
|
|
if (!engineOnline || !engineIgnited)
|
|
return;
|
|
|
|
// Smooth throttle changes to avoid instant jumps
|
|
effectiveThrottle = Mathf.MoveTowards(effectiveThrottle, throttleInput, Time.deltaTime / throttleRampTime);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates thrust and fuel flow based on current throttle and efficiency
|
|
/// </summary>
|
|
private void CalculateThrustAndFuelFlow()
|
|
{
|
|
// Base thrust from throttle curve and max thrust
|
|
thrust = throttleCurve.Evaluate(effectiveThrottle) * maxThrust * engineEfficiency;
|
|
|
|
// Fuel flow based on thrust and Isp
|
|
fuelFlowRate = thrust / (Isp * g);
|
|
|
|
// Request fuel from the tank if assigned
|
|
if (fuelTank != null)
|
|
{
|
|
float fuelRequested = fuelFlowRate * Time.deltaTime;
|
|
float fuelProvided = fuelTank.RequestFuel(fuelRequested);
|
|
if (fuelProvided < fuelRequested)
|
|
{
|
|
Debug.Log($"[MainEngine] Engine flameout: insufficient fuel (requested {fuelRequested:F3}, got {fuelProvided:F3}).");
|
|
engineIgnited = false;
|
|
effectiveThrottle = 0f;
|
|
thrust = 0f;
|
|
fuelFlowRate = 0f;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Only check for flameout if engine is fully ignited and grace period has passed
|
|
float nominalFlow = maxThrust / (Isp * g);
|
|
if (engineIgnited && postIgnitionTimer >= postIgnitionGrace && (fuelFlowRate / nominalFlow) < minStartupFlow)
|
|
{
|
|
Debug.Log($"[MainEngine] Engine flameout: fuel flow below minimum ({fuelFlowRate / nominalFlow:F3} < {minStartupFlow}).");
|
|
engineIgnited = false; // engine flameout
|
|
effectiveThrottle = 0f;
|
|
thrust = 0f;
|
|
fuelFlowRate = 0f;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Call to turn the engine on
|
|
/// </summary>
|
|
public void StartEngine()
|
|
{
|
|
if (!engineOnline)
|
|
{
|
|
// Prevent starting if not restartable and already started
|
|
if (!restartable && everStarted)
|
|
{
|
|
Debug.Log("[MainEngine] StartEngine() called but engine is not restartable and has already started.");
|
|
return;
|
|
}
|
|
|
|
Debug.Log("[MainEngine] Engine start command received.");
|
|
engineOnline = true;
|
|
startupTimer = 0f;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Call to turn the engine off
|
|
/// </summary>
|
|
public void ShutdownEngine()
|
|
{
|
|
Debug.Log("[MainEngine] Engine shutdown command received.");
|
|
engineOnline = false;
|
|
engineIgnited = false;
|
|
}
|
|
|
|
public void SetThrottle(float value)
|
|
{
|
|
throttleInput = Mathf.Clamp01(value);
|
|
}
|
|
}
|