Files
ScienceLab.FrictionForce/Assets/Scripts/Rocket/RocketFlightCore.cs
2026-05-29 18:30:19 +03:00

192 lines
5.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RocketFlightCore : MonoBehaviour
{
public enum FlightPhase
{
Idle, Ignition, LaunchPad, LowerAtmosphere, UpperAtmosphere, KarmanLine, Space, DeepSpace, Exploded, Landed
}
public FlightPhase Phase { get; private set; } = FlightPhase.Idle;
public float CurrentHeight { get; private set; }
public float Velocity { get; private set; }
public float MaxHeightReached { get; private set; }
public float AnimTime { get; private set; }
public bool FuelCutoff { get; private set; }
public bool RocketEscaped { get; private set; }
public bool IsActive { get; private set; }
public float TotalFuel { get; private set; }
public float RemainingFuel { get; private set; }
private float _gravity;
private float _atmDensity;
private float _materialDrag;
private float _thrust;
private float _animSpeed;
private float _fuelBurnRate;
private bool _willExplode;
private float _explodeDelay;
private float _explodeTimer;
private float _fuelCutoffTime;
private float _escapeVelocity;
public void Initialize() { }
public void StartFlight(float fuelAmount, float gravity, float atmDensity, float materialDrag, bool willExplode, float explodeDelay)
{
_gravity = gravity;
_atmDensity = atmDensity;
_materialDrag = materialDrag;
_willExplode = willExplode;
_explodeDelay = explodeDelay;
_thrust = Mathf.Max(10f, 200f - atmDensity * 1.5f - materialDrag * 30f);
_fuelBurnRate = 1f;
TotalFuel = fuelAmount;
RemainingFuel = fuelAmount;
_escapeVelocity = Mathf.Sqrt(2f * gravity * 6371000f) * 0.0001f;
float simFuelDuration = fuelAmount / _fuelBurnRate;
_animSpeed = simFuelDuration / 18f;
CurrentHeight = 0f;
Velocity = 0f;
MaxHeightReached = 0f;
AnimTime = 0f;
FuelCutoff = false;
RocketEscaped = false;
IsActive = true;
_explodeTimer = 0f;
_fuelCutoffTime = 0f;
Phase = FlightPhase.Ignition;
}
public void ResetFlight()
{
CurrentHeight = 0f;
Velocity = 0f;
MaxHeightReached = 0f;
AnimTime = 0f;
FuelCutoff = false;
RocketEscaped = false;
IsActive = false;
RemainingFuel = 0f;
Phase = FlightPhase.Idle;
}
public bool UpdateFlight(float deltaTime, out bool shouldExplode, out bool flightFinished)
{
shouldExplode = false;
flightFinished = false;
if (!IsActive) return false;
AnimTime += deltaTime;
float dt = deltaTime * _animSpeed;
if (_willExplode)
{
_explodeTimer += deltaTime;
if (_explodeTimer >= _explodeDelay)
{
shouldExplode = true;
Phase = FlightPhase.Exploded;
IsActive = false;
return true;
}
}
bool hasFuel = RemainingFuel > 0f;
float currentThrust = 0f;
if (hasFuel && !FuelCutoff)
{
currentThrust = _thrust;
RemainingFuel = Mathf.Max(0f, RemainingFuel - _fuelBurnRate * dt);
if (RemainingFuel <= 0f)
{
FuelCutoff = true;
_fuelCutoffTime = AnimTime;
}
}
float atmFactor = Mathf.Exp(-CurrentHeight * 0.00001f);
float drag = _atmDensity * atmFactor * Velocity * Velocity * _materialDrag * 0.0001f;
drag = Mathf.Sign(Velocity) * drag;
Velocity += (currentThrust - _gravity - drag) * dt;
CurrentHeight = Mathf.Max(0f, CurrentHeight + Velocity * dt);
if (CurrentHeight > MaxHeightReached) MaxHeightReached = CurrentHeight;
if (FuelCutoff && Velocity > _escapeVelocity * 0.5f)
RocketEscaped = true;
UpdatePhase();
if (AnimTime >= 25f || (FuelCutoff && CurrentHeight <= 0f && Velocity < 0f))
{
if (FuelCutoff && CurrentHeight <= 0f && Velocity < 0f)
{
shouldExplode = true;
Phase = FlightPhase.Exploded;
}
else
{
flightFinished = true;
}
IsActive = false;
return true;
}
return false;
}
private void UpdatePhase()
{
if (AnimTime < 0.5f)
Phase = FlightPhase.Ignition;
else if (CurrentHeight < 1000f)
Phase = FlightPhase.LaunchPad;
else if (CurrentHeight < 30000f)
Phase = FlightPhase.LowerAtmosphere;
else if (CurrentHeight < 80000f)
Phase = FlightPhase.UpperAtmosphere;
else if (CurrentHeight < 100000f)
Phase = FlightPhase.KarmanLine;
else if (CurrentHeight < 400000f)
Phase = FlightPhase.Space;
else
Phase = FlightPhase.DeepSpace;
}
public float GetAtmosphereProgress()
{
return Mathf.Clamp01(CurrentHeight / 100000f);
}
public float GetSpaceProgress()
{
return Mathf.Clamp01((CurrentHeight - 100000f) / 300000f);
}
public float GetSpeedNormalized()
{
return Mathf.Clamp01(Mathf.Abs(Velocity) / 150f);
}
public float GetFuelProgress()
{
return TotalFuel > 0f ? 1f - (RemainingFuel / TotalFuel) : 1f;
}
public float GetFuelCutoffTime()
{
return FuelCutoff ? AnimTime - _fuelCutoffTime : 0f;
}
}