using System.Collections; using System.Collections.Generic; using UnityEngine; public class MercuryEffects : MonoBehaviour { [Header("Метеорити")] public GameObject[] asteroidPrefabs; public GameObject explosionPrefab; public Material craterMaterial; public float spawnRadius = 80f; public float planetRadius = 4.879f; public float spawnInterval = 2f; public Transform mercuryTransform; [Header("Сонячний вітер")] public Transform sunTransform; public Material solarWindMaterial; [Header("Натрієве світіння")] public Material sodiumGlowMaterial; [Range(0f, 1f)] public float exosphereLevel = 1f; private float spawnTimer = 0f; private List craters = new List(); private ParticleSystem sodiumGlowSystem; private ParticleSystem solarWindSystem; public float previousLevel = 1f; public ParticleSystem SodiumGlowSystem => sodiumGlowSystem; public ParticleSystem SolarWindSystem => solarWindSystem; void Awake() { enabled = false; } public void InitState() { foreach (GameObject crater in craters) if (crater != null) Destroy(crater); craters.Clear(); if (solarWindSystem != null) Destroy(solarWindSystem.gameObject); if (sodiumGlowSystem != null) Destroy(sodiumGlowSystem.gameObject); solarWindSystem = null; sodiumGlowSystem = null; exosphereLevel = 1f; previousLevel = 1f; spawnTimer = 0f; CreateSodiumGlow(); CreateSolarWind(); } void CreateSodiumGlow() { GameObject obj = new GameObject("SodiumGlow"); obj.transform.parent = null; obj.transform.position = this.transform.position; obj.transform.localScale = Vector3.one * 2f; sodiumGlowSystem = obj.AddComponent(); var main = sodiumGlowSystem.main; main.loop = true; main.playOnAwake = true; main.maxParticles = 10000; main.startLifetime = new ParticleSystem.MinMaxCurve(5f, 10f); main.startSpeed = new ParticleSystem.MinMaxCurve(1f, 3f); main.startSize = new ParticleSystem.MinMaxCurve(0.3f, 0.8f); main.startColor = new ParticleSystem.MinMaxGradient( new Color(1f, 0.9f, 0.2f, 0.8f), new Color(1f, 0.7f, 0.1f, 0.5f) ); main.simulationSpace = ParticleSystemSimulationSpace.World; main.gravityModifier = 0f; var emission = sodiumGlowSystem.emission; emission.rateOverTime = 300f; var shape = sodiumGlowSystem.shape; shape.enabled = true; shape.shapeType = ParticleSystemShapeType.Sphere; shape.radius = planetRadius * 1.2f; shape.radiusThickness = 0.2f; var colorOverLifetime = sodiumGlowSystem.colorOverLifetime; colorOverLifetime.enabled = true; Gradient gradient = new Gradient(); gradient.SetKeys( new GradientColorKey[] { new GradientColorKey(new Color(1f, 0.9f, 0.2f), 0f), new GradientColorKey(new Color(1f, 0.7f, 0.1f), 0.5f), new GradientColorKey(new Color(1f, 0.5f, 0.0f), 1f) }, new GradientAlphaKey[] { new GradientAlphaKey(0f, 0f), new GradientAlphaKey(0.8f, 0.2f), new GradientAlphaKey(0.5f, 0.7f), new GradientAlphaKey(0f, 1f) } ); colorOverLifetime.color = new ParticleSystem.MinMaxGradient(gradient); var renderer = sodiumGlowSystem.GetComponent(); renderer.renderMode = ParticleSystemRenderMode.Billboard; renderer.sortingFudge = 5f; if (sodiumGlowMaterial != null) renderer.material = sodiumGlowMaterial; sodiumGlowSystem.Play(); } void CreateSolarWind() { GameObject obj = new GameObject("SolarWind"); obj.transform.parent = null; obj.transform.position = this.transform.position; obj.transform.localScale = Vector3.one * 3f; solarWindSystem = obj.AddComponent(); var main = solarWindSystem.main; main.loop = true; main.playOnAwake = false; main.maxParticles = 20000; main.startLifetime = new ParticleSystem.MinMaxCurve(2f, 4f); main.startSpeed = new ParticleSystem.MinMaxCurve(20f, 40f); main.startSize = new ParticleSystem.MinMaxCurve(0.2f, 0.6f); main.startColor = new ParticleSystem.MinMaxGradient( new Color(1f, 0.6f, 0.1f, 1f), new Color(1f, 0.8f, 0.3f, 0.7f) ); main.simulationSpace = ParticleSystemSimulationSpace.World; main.gravityModifier = 0f; var emission = solarWindSystem.emission; emission.rateOverTime = 0f; var shape = solarWindSystem.shape; shape.enabled = true; shape.shapeType = ParticleSystemShapeType.Cone; shape.angle = 20f; shape.radius = 15f; var colorOverLifetime = solarWindSystem.colorOverLifetime; colorOverLifetime.enabled = true; Gradient gradient = new Gradient(); gradient.SetKeys( new GradientColorKey[] { new GradientColorKey(new Color(1f, 0.8f, 0.3f), 0f), new GradientColorKey(new Color(1f, 0.4f, 0.1f), 0.5f), new GradientColorKey(new Color(0.8f, 0.2f, 0.0f), 1f) }, new GradientAlphaKey[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(0.5f, 0.7f), new GradientAlphaKey(0f, 1f) } ); colorOverLifetime.color = new ParticleSystem.MinMaxGradient(gradient); var renderer = solarWindSystem.GetComponent(); renderer.renderMode = ParticleSystemRenderMode.Billboard; renderer.sortingFudge = 3f; if (solarWindMaterial != null) renderer.material = solarWindMaterial; } void Update() { if (!Application.isPlaying) return; if (exosphereLevel >= 1f && previousLevel < 1f) InitState(); previousLevel = exosphereLevel; UpdateMercuryDeath(); UpdateSodiumGlow(); UpdateSolarWind(); UpdateMeteorSpawn(); } void UpdateMercuryDeath() { if (mercuryTransform == null) return; MercuryDeath md = mercuryTransform.GetComponent(); if (md == null) md = mercuryTransform.GetComponentInChildren(); if (md != null) md.exosphereLevel = exosphereLevel; } void UpdateSodiumGlow() { if (sodiumGlowSystem == null) return; var emission = sodiumGlowSystem.emission; if (exosphereLevel >= 1f) emission.rateOverTime = 300f; else if (exosphereLevel >= 0.7f) { float t = Mathf.InverseLerp(1f, 0.7f, exosphereLevel); emission.rateOverTime = Mathf.Lerp(300f, 150f, t); } else if (exosphereLevel >= 0.5f) { float t = Mathf.InverseLerp(0.7f, 0.5f, exosphereLevel); emission.rateOverTime = Mathf.Lerp(150f, 50f, t); } else if (exosphereLevel >= 0.3f) { float t = Mathf.InverseLerp(0.5f, 0.3f, exosphereLevel); emission.rateOverTime = Mathf.Lerp(50f, 10f, t); } else emission.rateOverTime = 0f; var main = sodiumGlowSystem.main; main.startColor = new ParticleSystem.MinMaxGradient( new Color(1f, 0.9f, 0.2f, exosphereLevel * 0.8f), new Color(1f, 0.7f, 0.1f, exosphereLevel * 0.5f) ); } void UpdateSolarWind() { if (solarWindSystem == null) return; if (sunTransform == null) return; Vector3 sunDir = (this.transform.position - sunTransform.position).normalized; solarWindSystem.transform.position = sunTransform.position + sunDir * 50f; solarWindSystem.transform.rotation = Quaternion.LookRotation(sunDir); var emission = solarWindSystem.emission; if (exosphereLevel <= 0.5f) { float t = Mathf.InverseLerp(0.5f, 0f, exosphereLevel); emission.rateOverTime = Mathf.Lerp(0f, 2000f, t); if (!solarWindSystem.isPlaying) solarWindSystem.Play(); } else emission.rateOverTime = 0f; } void UpdateMeteorSpawn() { if (exosphereLevel >= 1f) return; if (exosphereLevel <= 0f) return; spawnTimer += Time.deltaTime; float adjustedInterval; if (exosphereLevel >= 0.7f) adjustedInterval = spawnInterval; else if (exosphereLevel >= 0.5f) adjustedInterval = spawnInterval * 0.6f; else if (exosphereLevel >= 0.3f) adjustedInterval = spawnInterval * 0.3f; else adjustedInterval = 0.3f; if (spawnTimer >= adjustedInterval) { spawnTimer = 0f; SpawnAsteroid(); } } void SpawnAsteroid() { if (asteroidPrefabs == null || asteroidPrefabs.Length == 0) return; Vector3 direction = Random.onUnitSphere; Vector3 spawnPos = transform.position + direction * spawnRadius; Vector3 flyDir = -direction; GameObject prefab = asteroidPrefabs[Random.Range(0, asteroidPrefabs.Length)]; GameObject asteroid = Instantiate(prefab, spawnPos, Random.rotation); asteroid.transform.localScale = Vector3.one * Random.Range(0.2f, 0.6f); StartCoroutine(MoveAsteroid(asteroid, flyDir)); } IEnumerator MoveAsteroid(GameObject asteroid, Vector3 flyDir) { float speed = Random.Range(4f, 8f); while (asteroid != null) { asteroid.transform.position += flyDir * speed * Time.deltaTime; asteroid.transform.Rotate(Vector3.one * 60f * Time.deltaTime); float distFromCenter = Vector3.Distance(asteroid.transform.position, transform.position); if (distFromCenter <= planetRadius + 0.2f) { Vector3 hitPos = transform.position + (-flyDir) * planetRadius; if (explosionPrefab != null) { GameObject exp = Instantiate(explosionPrefab, hitPos, Quaternion.identity); exp.transform.localScale = Vector3.one * Random.Range(0.2f, 0.5f); Destroy(exp, 3f); } SpawnCrater(hitPos, -flyDir); Destroy(asteroid); yield break; } if (distFromCenter > spawnRadius * 2f) { Destroy(asteroid); yield break; } yield return null; } } void SpawnCrater(Vector3 pos, Vector3 flyDir) { if (craterMaterial == null) return; Vector3 center = mercuryTransform != null ? mercuryTransform.position : transform.position; Vector3 dirFromCenter = (pos - center).normalized; Vector3 surfacePos = center + dirFromCenter * (planetRadius + 0.02f); GameObject crater = GameObject.CreatePrimitive(PrimitiveType.Quad); crater.name = "Crater"; crater.transform.position = surfacePos; crater.transform.rotation = Quaternion.LookRotation(-dirFromCenter, Vector3.up); float size = Random.Range(0.3f, 0.8f); crater.transform.localScale = new Vector3(size, size, size); Destroy(crater.GetComponent()); Renderer r = crater.GetComponent(); r.material = craterMaterial; r.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; craters.Add(crater); } }