Files
ScienceLab.AtmosphericPressure/Assets/Scripts/StratosphereDeath.cs
2026-05-29 18:21:53 +03:00

304 lines
8.3 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StratosphereDeath : MonoBehaviour
{
[Header("Çâ'ÿçêè")]
public StratosphereEffects stratosphereEffects;
public PlanetDeath planetDeath;
[Header("Ïîæåæ³")]
public GameObject firePrefab;
public int maxFires = 50;
public float fireRadius = 6.4f;
[Header("Ñòàí")]
[Range(0f, 1f)]
public float stratosphereLevel = 1f;
private List<GameObject> activeFires = new List<GameObject>();
private List<GameObject> godRays = new List<GameObject>();
public bool planesStartedFalling = false;
public bool pearlCloudsGone = false;
private float previousLevel = 1f;
void Start()
{
StartCoroutine(CollectGodRaysDelayed());
}
IEnumerator CollectGodRaysDelayed()
{
yield return new WaitForSeconds(2f);
CollectGodRays();
}
void CollectGodRays()
{
godRays.Clear();
if (stratosphereEffects == null) return;
foreach (Transform child in stratosphereEffects.transform)
{
if (child.name.StartsWith("GodRay_"))
godRays.Add(child.gameObject);
}
}
void Update()
{
if (!Application.isPlaying) return;
if (godRays.Count == 0)
CollectGodRays();
UpdatePearlClouds();
UpdateGodRays();
UpdatePlanes();
UpdateFires();
UpdatePlanetTexture();
previousLevel = stratosphereLevel;
}
void UpdatePearlClouds()
{
if (stratosphereEffects == null) return;
if (stratosphereLevel < 0.7f && !pearlCloudsGone)
{
pearlCloudsGone = true;
foreach (Transform child in stratosphereEffects.transform)
{
if (child.name.StartsWith("PearlCloud_"))
StartCoroutine(FadeOutAndDestroy(child.gameObject, 3f));
}
}
if (stratosphereLevel >= 0.7f && pearlCloudsGone)
{
pearlCloudsGone = false;
stratosphereEffects.SpawnPearlClouds();
}
}
void UpdateGodRays()
{
foreach (GameObject ray in godRays)
{
if (ray == null) continue;
ParticleSystem ps = ray.GetComponent<ParticleSystem>();
if (ps == null) continue;
var main = ps.main;
if (stratosphereLevel >= 0.7f)
{
main.startColor = new Color(1f, 0.95f, 0.6f, 0.2f);
ray.transform.localScale = new Vector3(0.2f, 0.2f, 0.8f);
}
else if (stratosphereLevel >= 0.5f)
{
float t = Mathf.InverseLerp(0.7f, 0.5f, stratosphereLevel);
main.startColor = new Color(1f, 0.95f, 0.6f, Mathf.Lerp(0.2f, 0.6f, t));
ray.transform.localScale = new Vector3(
Mathf.Lerp(0.2f, 0.4f, t),
Mathf.Lerp(0.2f, 0.4f, t),
Mathf.Lerp(0.8f, 2f, t)
);
}
else
{
float t = Mathf.InverseLerp(0.5f, 0f, stratosphereLevel);
main.startColor = new Color(1f, 0.85f, 0.4f, Mathf.Lerp(0.6f, 1f, t));
ray.transform.localScale = new Vector3(
Mathf.Lerp(0.4f, 0.7f, t),
Mathf.Lerp(0.4f, 0.7f, t),
Mathf.Lerp(2f, 4f, t)
);
}
}
}
void UpdatePlanes()
{
if (stratosphereEffects == null) return;
if (stratosphereLevel >= 1f && planesStartedFalling)
{
ResetState();
return;
}
if (stratosphereLevel <= 0.3f && !planesStartedFalling)
{
planesStartedFalling = true;
StartCoroutine(DropPlanesSequentially());
}
}
IEnumerator DropPlanesSequentially()
{
List<Transform> planes = new List<Transform>();
foreach (Transform child in stratosphereEffects.transform)
{
if (child.name.StartsWith("Plane_"))
planes.Add(child);
}
foreach (Transform plane in planes)
{
if (plane == null) continue;
yield return new WaitForSeconds(Random.Range(0.2f, 0.8f));
StartCoroutine(DropPlane(plane));
}
}
IEnumerator DropPlane(Transform plane)
{
float elapsed = 0f;
Vector3 fallDir = (Vector3.zero - plane.position).normalized;
float fallSpeed = Random.Range(3f, 6f);
while (elapsed < 3f && plane != null)
{
plane.position += fallDir * fallSpeed * Time.deltaTime;
plane.Rotate(Random.insideUnitSphere * 50f * Time.deltaTime);
elapsed += Time.deltaTime;
yield return null;
}
if (plane != null)
{
SpawnFire(plane.position);
Destroy(plane.gameObject);
}
}
void UpdateFires()
{
activeFires.RemoveAll(f => f == null);
if (stratosphereLevel < 0.7f && stratosphereLevel > 0.1f)
{
int targetFires = Mathf.RoundToInt(Mathf.Lerp(0, maxFires, Mathf.InverseLerp(0.7f, 0.3f, stratosphereLevel)));
if (activeFires.Count < targetFires && Random.value < 0.15f)
SpawnFire(transform.position + Random.onUnitSphere * fireRadius);
}
else if (stratosphereLevel <= 0.1f)
{
foreach (GameObject fire in activeFires)
{
if (fire != null) StartCoroutine(FadeOutAndDestroy(fire, 2f));
}
activeFires.Clear();
}
}
void SpawnFire(Vector3 position)
{
if (firePrefab == null) return;
Vector3 dirFromCenter = (position - transform.position).normalized;
Vector3 surfacePos = transform.position + dirFromCenter * fireRadius;
Quaternion fireRot = Quaternion.FromToRotation(Vector3.up, dirFromCenter);
GameObject fire = Instantiate(firePrefab, surfacePos, fireRot);
fire.transform.localScale = Vector3.one * Random.Range(0.1f, 0.3f);
activeFires.Add(fire);
StartCoroutine(AutoDestroyFire(fire, Random.Range(8f, 15f)));
}
public void TriggerPlanesDown()
{
if (!planesStartedFalling)
{
planesStartedFalling = true;
StartCoroutine(DropPlanesSequentially());
}
}
public void InitState()
{
ResetState();
StartCoroutine(RespawnAfterInit());
}
IEnumerator RespawnAfterInit()
{
yield return null;
if (stratosphereEffects != null)
{
stratosphereEffects.SpawnPlanes();
stratosphereEffects.SpawnPearlClouds();
}
yield return new WaitForSeconds(0.5f);
CollectGodRays();
}
public void ResetState()
{
StopAllCoroutines();
planesStartedFalling = false;
pearlCloudsGone = false;
foreach (GameObject fire in activeFires)
if (fire != null) Destroy(fire);
activeFires.Clear();
if (stratosphereEffects != null)
{
foreach (Transform child in stratosphereEffects.transform)
{
if (child.name.StartsWith("Plane_"))
Destroy(child.gameObject);
if (child.name.StartsWith("PearlCloud_"))
Destroy(child.gameObject);
}
}
godRays.Clear();
stratosphereLevel = 1f;
}
IEnumerator RespawnAfterReset()
{
yield return null;
stratosphereEffects.SpawnPlanes();
stratosphereEffects.SpawnPearlClouds();
yield return new WaitForSeconds(0.5f);
CollectGodRays();
}
IEnumerator AutoDestroyFire(GameObject fire, float delay)
{
yield return new WaitForSeconds(delay);
if (fire != null)
{
activeFires.Remove(fire);
StartCoroutine(FadeOutAndDestroy(fire, 2f));
}
}
IEnumerator FadeOutAndDestroy(GameObject obj, float duration)
{
float elapsed = 0f;
while (elapsed < duration && obj != null)
{
elapsed += Time.deltaTime;
yield return null;
}
if (obj != null) Destroy(obj);
}
void UpdatePlanetTexture()
{
if (planetDeath == null) return;
planetDeath.stratosphereLevel = stratosphereLevel;
}
}