using System.Collections; using System.Collections.Generic; using UnityEngine; [ExecuteAlways] public class AtmosphereSystem : MonoBehaviour { public float earthRadiusUnits = 6.371f; public float heightMultiplier = 50f; private struct LayerData { public string name; public float altitudeStartKm; public float altitudeEndKm; public Color color; public float opacity; public string description; } private LayerData[] layers = new LayerData[] { new LayerData { name = "Troposphere", altitudeStartKm = 0f, altitudeEndKm = 12f, color = new Color(0.40f, 0.75f, 1.00f), opacity = 0.55f, description = "0-12 км. Повітря, погода, хмари." }, new LayerData { name = "Stratosphere", altitudeStartKm = 12f, altitudeEndKm = 50f, color = new Color(0.20f, 0.50f, 0.90f), opacity = 0.45f, description = "12-50 км. Озоновий шар, UV." }, new LayerData { name = "Mesosphere", altitudeStartKm = 50f, altitudeEndKm = 85f, color = new Color(0.10f, 0.25f, 0.70f), opacity = 0.38f, description = "50-85 км. Метеорити згоряють." }, new LayerData { name = "Thermosphere", altitudeStartKm = 85f, altitudeEndKm = 600f, color = new Color(0.05f, 0.10f, 0.50f), opacity = 0.28f, description = "85-600 км. МКС, полярне сяйво." }, new LayerData { name = "Exosphere", altitudeStartKm = 600f, altitudeEndKm = 10000f, color = new Color(0.15f, 0.10f, 0.45f), opacity = 0.22f, description = "600-10000 км. Перехід до космосу." } }; void Start() { } void OnEnable() { if (!Application.isPlaying && transform.childCount == 0) BuildLayers(); } [ContextMenu("Перебудувати шари")] public void BuildLayers() { DestroyOldLayers(); for (int i = 0; i < layers.Length; i++) CreateLayerSphere(layers[i]); } GameObject CreateLayerSphere(LayerData data) { float radiusUnits = earthRadiusUnits + (data.altitudeEndKm / 1000f) * heightMultiplier; GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere); obj.name = "Layer_" + data.name; obj.transform.parent = this.transform; obj.transform.localPosition = Vector3.zero; obj.transform.localScale = Vector3.one * radiusUnits * 2f; if (Application.isPlaying) Destroy(obj.GetComponent()); else DestroyImmediate(obj.GetComponent()); obj.GetComponent().material = CreateURPMaterial(data.color, data.opacity); AtmosphereLayer layerComp = obj.AddComponent(); layerComp.layerName = data.name; layerComp.altitudeStartKm = data.altitudeStartKm; layerComp.altitudeEndKm = data.altitudeEndKm; layerComp.description = data.description; return obj; } Material CreateURPMaterial(Color color, float opacity) { Material mat = new Material(Shader.Find("Custom/AtmosphereLayer")); Color coreColor = new Color(color.r * 0.2f, color.g * 0.3f, color.b * 0.6f, opacity * 0.5f); mat.SetColor("_RimColor", color); mat.SetColor("_CoreColor", coreColor); mat.SetFloat("_RimPower", 1.5f); mat.SetFloat("_RimIntensity", 2.5f); mat.SetFloat("_CoreIntensity", 0.4f); mat.SetFloat("_PulseSpeed", 0.8f); mat.SetFloat("_PulseStrength", 0.15f); return mat; } void DestroyOldLayers() { for (int i = transform.childCount - 1; i >= 0; i--) { Transform child = transform.GetChild(i); if (child.name.StartsWith("Layer_")) { if (Application.isPlaying) Destroy(child.gameObject); else DestroyImmediate(child.gameObject); } } } public void SetLayerVisible(int index, bool visible) { Transform child = transform.Find("Layer_" + layers[index].name); if (child != null) child.gameObject.SetActive(visible); } public int GetLayerCount() => layers.Length; }