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

320 lines
11 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlanetDeath : MonoBehaviour
{
[Header("Òåêñòóðè -- Òðîïîñôåðà")]
public Texture2D tropo100;
public Texture2D tropo70;
public Texture2D tropo50;
public Texture2D tropo30;
public Texture2D tropo0;
[Header("Òåêñòóðè -- Ñòðàòîñôåðà")]
public Texture2D strato100;
public Texture2D strato70;
public Texture2D strato50;
public Texture2D strato30;
public Texture2D strato0;
[Header("Ìåðòâà ïëàíåòà")]
public Texture2D deadPlanetTexture;
[Header("Òåêñòóðè -- Òåðìîñôåðà")]
public Texture2D thermo100;
public Texture2D thermo70;
public Texture2D thermo50;
public Texture2D thermo30;
public Texture2D thermo0;
[Header("гâí³ øàð³â")]
[Range(0f, 1f)] public float troposphereLevel = 1f;
[Range(0f, 1f)] public float stratosphereLevel = 1f;
[Range(0f, 1f)] public float mesosphereLevel = 1f;
[Range(0f, 1f)] public float thermosphereLevel = 1f;
[Range(0f, 1f)] public float exosphereLevel = 1f;
[Header("Çâ'ÿçêè")]
public TroposphereEffects troposphere;
public GameObject troposphereLayerObject;
public GameObject stratosphereLayerObject;
public GameObject mesosphereLayerObject;
public GameObject thermosphereLayerObject;
public GameObject exosphereLayerObject;
[Header("Âèïàðîâóâàííÿ")]
public bool showEvaporation = true;
public Material evaporationMaterial;
private Renderer planetRenderer;
private Material mat;
private ParticleSystem evaporationSystem;
private Texture2D currentBlended;
private float prevTropo = -1f;
private float prevStrato = -1f;
private float prevThermo = -1f;
void Start()
{
planetRenderer = GetComponent<Renderer>();
mat = planetRenderer.material;
currentBlended = new Texture2D(tropo100.width, tropo100.height, TextureFormat.RGB24, false);
if (showEvaporation)
CreateEvaporationEffect();
}
public void ResetTextureCache()
{
prevTropo = -1f;
prevStrato = -1f;
prevThermo = -1f;
}
void Update()
{
if (mat == null) return;
UpdateTexture();
UpdateAtmosphereLayers();
UpdateWeather();
UpdateEvaporation();
StratosphereDeath strato = stratosphereLayerObject?.GetComponent<StratosphereDeath>();
if (strato != null) strato.stratosphereLevel = stratosphereLevel;
MesosphereEffects meso = mesosphereLayerObject?.GetComponent<MesosphereEffects>();
if (meso != null) meso.mesosphereLevel = mesosphereLevel;
ThermosphereEffects thermo = thermosphereLayerObject?.GetComponent<ThermosphereEffects>();
if (thermo != null) thermo.thermosphereLevel = thermosphereLevel;
ExosphereEffects exo = exosphereLayerObject?.GetComponent<ExosphereEffects>();
if (exo != null) exo.exosphereLevel = exosphereLevel;
}
void UpdateTexture()
{
bool isDead = troposphereLevel <= 0f || stratosphereLevel <= 0f || thermosphereLevel <= 0f;
if (isDead)
{
if (deadPlanetTexture != null)
mat.mainTexture = deadPlanetTexture;
UpdateLayerMaterial(troposphereLayerObject, 0f);
UpdateLayerMaterial(stratosphereLayerObject, 0f);
UpdateLayerMaterial(mesosphereLayerObject, 0f);
UpdateLayerMaterial(thermosphereLayerObject, 0f);
UpdateLayerMaterial(exosphereLayerObject, 0f);
return;
}
else
{
troposphereLayerObject?.SetActive(true);
stratosphereLayerObject?.SetActive(true);
mesosphereLayerObject?.SetActive(true);
thermosphereLayerObject?.SetActive(true);
exosphereLayerObject?.SetActive(true);
}
if (Mathf.Approximately(troposphereLevel, prevTropo) &&
Mathf.Approximately(stratosphereLevel, prevStrato) &&
Mathf.Approximately(thermosphereLevel, prevThermo)) return;
prevTropo = troposphereLevel;
prevStrato = stratosphereLevel;
prevThermo = thermosphereLevel;
Texture2D tropoTex = GetLayerTexture(troposphereLevel, tropo100, tropo70, tropo50, tropo30, tropo0);
Texture2D stratoTex = GetLayerTexture(stratosphereLevel, strato100, strato70, strato50, strato30, strato0);
Texture2D thermoTex = GetLayerTexture(thermosphereLevel, thermo100, thermo70, thermo50, thermo30, thermo0);
if (tropoTex == null || stratoTex == null) return;
Color[] tropoPixels = tropoTex.GetPixels();
Color[] stratoPixels = stratoTex.GetPixels();
Color[] thermoPixels = thermoTex != null ? thermoTex.GetPixels() : null;
Color[] basePixels = tropo100.GetPixels();
Color[] output = new Color[tropoPixels.Length];
for (int i = 0; i < output.Length; i++)
{
Color col = basePixels[i];
if (troposphereLevel < 1f)
col = Color.Lerp(col, tropoPixels[i], 1f - troposphereLevel);
if (stratosphereLevel < 1f)
col = Color.Lerp(col, stratoPixels[i], 1f - stratosphereLevel);
if (thermosphereLevel < 1f && thermoPixels != null)
col = Color.Lerp(col, thermoPixels[i], 1f - thermosphereLevel);
output[i] = col;
}
currentBlended.SetPixels(output);
currentBlended.Apply();
mat.mainTexture = currentBlended;
}
Texture2D GetLayerTexture(float level, Texture2D t100, Texture2D t70, Texture2D t50, Texture2D t30, Texture2D t0)
{
if (level >= 0.85f) return Blend(t100, t70, Mathf.InverseLerp(1.0f, 0.85f, level));
else if (level >= 0.6f) return Blend(t70, t50, Mathf.InverseLerp(0.85f, 0.6f, level));
else if (level >= 0.4f) return Blend(t50, t30, Mathf.InverseLerp(0.6f, 0.4f, level));
else return Blend(t30, t0, Mathf.InverseLerp(0.4f, 0f, level));
}
Texture2D Blend(Texture2D a, Texture2D b, float t)
{
if (t <= 0f || a == null) return a;
if (t >= 1f || b == null) return b;
if (t < 0.5f) return a;
return b;
}
void UpdateAtmosphereLayers()
{
bool isDead = troposphereLevel <= 0f || stratosphereLevel <= 0f ||
thermosphereLevel <= 0f || exosphereLevel <= 0f;
if (isDead)
{
UpdateLayerMaterial(troposphereLayerObject, 0f);
UpdateLayerMaterial(stratosphereLayerObject, 0f);
UpdateLayerMaterial(mesosphereLayerObject, 0f);
UpdateLayerMaterial(thermosphereLayerObject, 0f);
UpdateLayerMaterial(exosphereLayerObject, 0f);
return;
}
UpdateLayerMaterial(troposphereLayerObject, troposphereLevel);
UpdateLayerMaterial(stratosphereLayerObject, stratosphereLevel);
UpdateLayerMaterial(mesosphereLayerObject, mesosphereLevel);
UpdateLayerMaterial(thermosphereLayerObject, thermosphereLevel);
UpdateLayerMaterial(exosphereLayerObject, exosphereLevel);
}
void UpdateLayerMaterial(GameObject layerObj, float level)
{
if (layerObj == null) return;
Renderer r = layerObj.GetComponent<Renderer>();
if (r == null) return;
Material layerMat = r.material;
layerMat.SetFloat("_RimIntensity", Mathf.Lerp(0f, 2.5f, level));
layerMat.SetFloat("_CoreIntensity", Mathf.Lerp(0f, 0.4f, level));
}
void UpdateWeather()
{
if (troposphere == null) return;
bool isDead = troposphereLevel <= 0f || stratosphereLevel <= 0f ||
mesosphereLevel <= 0f || thermosphereLevel <= 0f ||
exosphereLevel <= 0f;
if (isDead)
{
troposphere.SetRainEnabled(false);
troposphere.SetCloudsEnabled(false);
return;
}
float combinedLevel = Mathf.Min(troposphereLevel, stratosphereLevel);
if (combinedLevel < 0.5f)
troposphere.SetRainEnabled(false);
else
troposphere.SetRainEnabled(troposphereLevel >= 0.8f);
if (combinedLevel < 0.4f)
troposphere.SetCloudsEnabled(false);
else
troposphere.SetCloudsEnabled(troposphereLevel >= 0.6f);
if (combinedLevel < 0.2f)
troposphere.gameObject.SetActive(false);
else
troposphere.gameObject.SetActive(true);
}
void UpdateEvaporation()
{
if (evaporationSystem == null) return;
var emission = evaporationSystem.emission;
var main = evaporationSystem.main;
if (troposphereLevel <= 0.5f && troposphereLevel > 0.05f)
{
float t = Mathf.InverseLerp(0.5f, 0.05f, troposphereLevel);
emission.rateOverTime = Mathf.Lerp(100f, 10000f, t);
main.startSize = new ParticleSystem.MinMaxCurve(
Mathf.Lerp(0.02f, 0.15f, t),
Mathf.Lerp(0.08f, 0.3f, t)
);
}
else
{
emission.rateOverTime = 0f;
}
}
void CreateEvaporationEffect()
{
GameObject obj = new GameObject("EvaporationParticles");
obj.transform.parent = null;
obj.transform.position = this.transform.position;
evaporationSystem = obj.AddComponent<ParticleSystem>();
var main = evaporationSystem.main;
main.loop = true;
main.playOnAwake = true;
main.maxParticles = 20000;
main.startLifetime = new ParticleSystem.MinMaxCurve(2f, 5f);
main.startSpeed = new ParticleSystem.MinMaxCurve(1f, 3f);
main.startSize = new ParticleSystem.MinMaxCurve(0.05f, 0.15f);
main.startColor = new ParticleSystem.MinMaxGradient(
new Color(0.4f, 0.7f, 1.0f, 1f),
new Color(0.6f, 0.85f, 1.0f, 0.8f)
);
main.simulationSpace = ParticleSystemSimulationSpace.World;
main.gravityModifier = 0f;
var emission = evaporationSystem.emission;
emission.rateOverTime = 0f;
var shape = evaporationSystem.shape;
shape.enabled = true;
shape.shapeType = ParticleSystemShapeType.Sphere;
shape.radius = 6.4f;
shape.radiusThickness = 0f;
var colorOverLifetime = evaporationSystem.colorOverLifetime;
colorOverLifetime.enabled = true;
Gradient gradient = new Gradient();
gradient.SetKeys(
new GradientColorKey[] {
new GradientColorKey(new Color(0.4f, 0.7f, 1.0f), 0f),
new GradientColorKey(new Color(0.8f, 0.9f, 1.0f), 1f)
},
new GradientAlphaKey[] {
new GradientAlphaKey(1f, 0f),
new GradientAlphaKey(0f, 1f)
}
);
colorOverLifetime.color = new ParticleSystem.MinMaxGradient(gradient);
var psRenderer = evaporationSystem.GetComponent<ParticleSystemRenderer>();
psRenderer.renderMode = ParticleSystemRenderMode.Billboard;
psRenderer.sortingFudge = 5f;
if (evaporationMaterial != null)
psRenderer.material = evaporationMaterial;
evaporationSystem.Play();
}
}