114 lines
4.0 KiB
C#
114 lines
4.0 KiB
C#
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<Collider>());
|
|
else
|
|
DestroyImmediate(obj.GetComponent<Collider>());
|
|
|
|
obj.GetComponent<Renderer>().material = CreateURPMaterial(data.color, data.opacity);
|
|
|
|
AtmosphereLayer layerComp = obj.AddComponent<AtmosphereLayer>();
|
|
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;
|
|
}
|