initial commit
This commit is contained in:
357
Assets/Scripts/TroposphereEffects.cs
Normal file
357
Assets/Scripts/TroposphereEffects.cs
Normal file
@@ -0,0 +1,357 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class TroposphereEffects : MonoBehaviour
|
||||
{
|
||||
[Header("Ìàòåð³àëè õìàð")]
|
||||
public Material[] cloudMaterials;
|
||||
|
||||
[Header("Äîù")]
|
||||
public GameObject rainPrefab;
|
||||
|
||||
[Header("Õìàðè")]
|
||||
public int cloudGroupCount = 20;
|
||||
public int particlesPerCloud = 4;
|
||||
public float cloudGroupSpread = 0.4f;
|
||||
public float cloudMinSize = 0.8f;
|
||||
public float cloudMaxSize = 1.8f;
|
||||
public float cloudOrbitSpeed = 0.5f;
|
||||
|
||||
[Header("Äîùîâ³ õìàðè")]
|
||||
public int rainCloudGroupCount = 5;
|
||||
public float rainDuration = 15f;
|
||||
public float rainPause = 10f;
|
||||
|
||||
private float cloudRadius;
|
||||
private Vector3 planetCenter;
|
||||
|
||||
[Header("Òóìàí")]
|
||||
public Material fogMaterial;
|
||||
|
||||
private class RainCloud
|
||||
{
|
||||
public List<CloudPuff> puffs = new List<CloudPuff>();
|
||||
public GameObject rainInstance;
|
||||
public GameObject fogInstance;
|
||||
public float timer;
|
||||
public bool isRaining;
|
||||
public bool isFogging;
|
||||
public Vector3 position;
|
||||
}
|
||||
|
||||
private class CloudPuff
|
||||
{
|
||||
public Transform transform;
|
||||
public float orbitSpeed;
|
||||
public Vector3 orbitAxis;
|
||||
}
|
||||
|
||||
private List<CloudPuff> cloudPuffs = new List<CloudPuff>();
|
||||
private List<RainCloud> rainClouds = new List<RainCloud>();
|
||||
private Transform cloudRoot;
|
||||
|
||||
void Start()
|
||||
{
|
||||
planetCenter = this.transform.position;
|
||||
cloudRadius = this.transform.lossyScale.x * 0.5f * 0.95f;
|
||||
SpawnCloudGroups();
|
||||
SpawnRainClouds();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SpawnCloudGroups()
|
||||
{
|
||||
cloudRoot = new GameObject("CloudParticles").transform;
|
||||
cloudRoot.parent = this.transform;
|
||||
cloudRoot.localPosition = Vector3.zero;
|
||||
|
||||
for (int i = 0; i < cloudGroupCount; i++)
|
||||
{
|
||||
Vector3 groupCenter = planetCenter + Random.onUnitSphere * cloudRadius;
|
||||
Vector3 toCenter = (planetCenter - groupCenter).normalized;
|
||||
Vector3 axis = Quaternion.AngleAxis(Random.Range(-20f, 20f), Random.onUnitSphere) * Vector3.up;
|
||||
float speed = cloudOrbitSpeed * Random.Range(0.7f, 1.3f);
|
||||
|
||||
for (int j = 0; j < particlesPerCloud; j++)
|
||||
{
|
||||
Vector3 pos = groupCenter + (Vector3)Random.insideUnitSphere * cloudGroupSpread;
|
||||
CloudPuff puff = CreateCloudPuff(cloudRoot, pos, toCenter, axis, speed, false, i);
|
||||
cloudPuffs.Add(puff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GameObject CreateFog(Vector3 position)
|
||||
{
|
||||
GameObject fogObj = new GameObject("Fog");
|
||||
fogObj.transform.parent = cloudRoot;
|
||||
fogObj.transform.position = position;
|
||||
|
||||
ParticleSystem ps = fogObj.AddComponent<ParticleSystem>();
|
||||
|
||||
var main = ps.main;
|
||||
main.loop = true;
|
||||
main.playOnAwake = true;
|
||||
main.maxParticles = 80;
|
||||
main.startLifetime = new ParticleSystem.MinMaxCurve(10f, 16f);
|
||||
main.startSpeed = new ParticleSystem.MinMaxCurve(0.03f, 0.08f);
|
||||
main.startSize = new ParticleSystem.MinMaxCurve(0.2f, 0.6f);
|
||||
main.startColor = new ParticleSystem.MinMaxGradient(
|
||||
new Color(0.88f, 0.92f, 0.95f, 0.18f),
|
||||
new Color(0.95f, 0.97f, 1f, 0.09f)
|
||||
);
|
||||
main.startRotation = new ParticleSystem.MinMaxCurve(0f, 360f * Mathf.Deg2Rad);
|
||||
main.simulationSpace = ParticleSystemSimulationSpace.World;
|
||||
|
||||
var emission = ps.emission;
|
||||
emission.rateOverTime = 8f;
|
||||
|
||||
var shape = ps.shape;
|
||||
shape.enabled = true;
|
||||
shape.shapeType = ParticleSystemShapeType.Sphere;
|
||||
shape.radius = cloudGroupSpread * 2.5f;
|
||||
shape.radiusThickness = 1f;
|
||||
|
||||
var velocityOverLifetime = ps.velocityOverLifetime;
|
||||
velocityOverLifetime.enabled = true;
|
||||
velocityOverLifetime.space = ParticleSystemSimulationSpace.World;
|
||||
Vector3 tangent = Vector3.Cross((planetCenter - position).normalized, Vector3.up).normalized;
|
||||
velocityOverLifetime.x = new ParticleSystem.MinMaxCurve(tangent.x * 0.08f - 0.04f, tangent.x * 0.08f + 0.04f);
|
||||
velocityOverLifetime.y = new ParticleSystem.MinMaxCurve(-0.01f, 0.01f);
|
||||
velocityOverLifetime.z = new ParticleSystem.MinMaxCurve(tangent.z * 0.08f - 0.04f, tangent.z * 0.08f + 0.04f);
|
||||
|
||||
var sizeOverLifetime = ps.sizeOverLifetime;
|
||||
sizeOverLifetime.enabled = true;
|
||||
AnimationCurve curve = new AnimationCurve();
|
||||
curve.AddKey(0f, 0f);
|
||||
curve.AddKey(0.15f, 1f);
|
||||
curve.AddKey(0.75f, 0.85f);
|
||||
curve.AddKey(1f, 0f);
|
||||
sizeOverLifetime.size = new ParticleSystem.MinMaxCurve(1f, curve);
|
||||
|
||||
var colorOverLifetime = ps.colorOverLifetime;
|
||||
colorOverLifetime.enabled = true;
|
||||
Gradient gradient = new Gradient();
|
||||
gradient.SetKeys(
|
||||
new GradientColorKey[] {
|
||||
new GradientColorKey(new Color(0.88f, 0.92f, 0.95f), 0f),
|
||||
new GradientColorKey(new Color(0.95f, 0.97f, 1f), 0.5f),
|
||||
new GradientColorKey(new Color(0.88f, 0.92f, 0.95f), 1f)
|
||||
},
|
||||
new GradientAlphaKey[] {
|
||||
new GradientAlphaKey(0f, 0f),
|
||||
new GradientAlphaKey(0.18f, 0.2f),
|
||||
new GradientAlphaKey(0.12f, 0.7f),
|
||||
new GradientAlphaKey(0f, 1f)
|
||||
}
|
||||
);
|
||||
colorOverLifetime.color = new ParticleSystem.MinMaxGradient(gradient);
|
||||
|
||||
var rotationOverLifetime = ps.rotationOverLifetime;
|
||||
rotationOverLifetime.enabled = true;
|
||||
rotationOverLifetime.z = new ParticleSystem.MinMaxCurve(-0.2f, 0.2f);
|
||||
|
||||
var renderer = ps.GetComponent<ParticleSystemRenderer>();
|
||||
renderer.renderMode = ParticleSystemRenderMode.Billboard;
|
||||
renderer.sortingFudge = -3f;
|
||||
|
||||
if (fogMaterial != null)
|
||||
renderer.material = fogMaterial;
|
||||
|
||||
ps.Play();
|
||||
|
||||
return fogObj;
|
||||
}
|
||||
|
||||
void SpawnRainClouds()
|
||||
{
|
||||
for (int i = 0; i < rainCloudGroupCount; i++)
|
||||
{
|
||||
RainCloud rc = CreateRainCloud();
|
||||
rainClouds.Add(rc);
|
||||
}
|
||||
}
|
||||
|
||||
RainCloud CreateRainCloud()
|
||||
{
|
||||
RainCloud rc = new RainCloud();
|
||||
rc.position = planetCenter + Random.onUnitSphere * cloudRadius;
|
||||
rc.timer = Random.Range(0f, rainDuration);
|
||||
rc.isRaining = true;
|
||||
|
||||
Vector3 toCenter = (planetCenter - rc.position).normalized;
|
||||
Vector3 axis = Quaternion.AngleAxis(Random.Range(-20f, 20f), Random.onUnitSphere) * Vector3.up;
|
||||
float speed = cloudOrbitSpeed * Random.Range(0.6f, 1.0f);
|
||||
|
||||
for (int j = 0; j < particlesPerCloud; j++)
|
||||
{
|
||||
Vector3 pos = rc.position + (Vector3)Random.insideUnitSphere * cloudGroupSpread;
|
||||
CloudPuff puff = CreateCloudPuff(cloudRoot, pos, toCenter, axis, speed, true, j);
|
||||
rc.puffs.Add(puff);
|
||||
cloudPuffs.Add(puff);
|
||||
}
|
||||
|
||||
if (rainPrefab != null)
|
||||
{
|
||||
Vector3 dirToCenter = (planetCenter - rc.position).normalized;
|
||||
Vector3 rainPos = rc.position + dirToCenter * (cloudGroupSpread + 0.9f);
|
||||
rc.rainInstance = Instantiate(rainPrefab, rainPos, Quaternion.identity);
|
||||
rc.rainInstance.transform.parent = cloudRoot;
|
||||
rc.rainInstance.transform.localScale = Vector3.one * 0.5f;
|
||||
|
||||
RainDirector director = rc.rainInstance.AddComponent<RainDirector>();
|
||||
director.planetCenter = planetCenter;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
CloudPuff CreateCloudPuff(Transform parent, Vector3 pos, Vector3 toCenter, Vector3 axis, float speed, bool dark, int texIndex)
|
||||
{
|
||||
ParticleSystem ps = new GameObject("CloudPuff").AddComponent<ParticleSystem>();
|
||||
ps.transform.parent = parent;
|
||||
ps.transform.position = pos;
|
||||
|
||||
var main = ps.main;
|
||||
main.loop = false;
|
||||
main.playOnAwake = true;
|
||||
main.maxParticles = 1;
|
||||
main.startLifetime = 999f;
|
||||
main.startSpeed = 0f;
|
||||
main.startSize = Random.Range(cloudMinSize, cloudMaxSize);
|
||||
main.startColor = dark
|
||||
? new Color(Random.Range(0.1f, 0.3f), Random.Range(0.1f, 0.3f), Random.Range(0.1f, 0.3f), Random.Range(0.7f, 0.9f))
|
||||
: new Color(Random.Range(0.88f, 1f), Random.Range(0.88f, 1f), 1f, Random.Range(0.55f, 0.8f));
|
||||
main.simulationSpace = ParticleSystemSimulationSpace.Local;
|
||||
|
||||
var emission = ps.emission;
|
||||
emission.rateOverTime = 0f;
|
||||
emission.SetBursts(new ParticleSystem.Burst[] { new ParticleSystem.Burst(0f, 1) });
|
||||
|
||||
var shape = ps.shape;
|
||||
shape.enabled = false;
|
||||
|
||||
var renderer = ps.GetComponent<ParticleSystemRenderer>();
|
||||
renderer.renderMode = ParticleSystemRenderMode.Billboard;
|
||||
renderer.sortingFudge = -10f;
|
||||
|
||||
if (cloudMaterials != null && cloudMaterials.Length > 0)
|
||||
{
|
||||
renderer.material = cloudMaterials[texIndex % cloudMaterials.Length];
|
||||
}
|
||||
else
|
||||
{
|
||||
Material mat = new Material(Shader.Find("Universal Render Pipeline/Particles/Unlit"));
|
||||
mat.SetFloat("_Surface", 1f);
|
||||
mat.SetFloat("_Blend", 0f);
|
||||
mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
|
||||
mat.renderQueue = 3001;
|
||||
mat.SetColor("_BaseColor", main.startColor.color);
|
||||
renderer.material = mat;
|
||||
}
|
||||
|
||||
ps.Play();
|
||||
|
||||
return new CloudPuff
|
||||
{
|
||||
transform = ps.transform,
|
||||
orbitSpeed = speed,
|
||||
orbitAxis = axis
|
||||
};
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (!Application.isPlaying) return;
|
||||
|
||||
Quaternion globalRotation = Quaternion.AngleAxis(cloudOrbitSpeed * Time.deltaTime, Vector3.up);
|
||||
|
||||
foreach (CloudPuff puff in cloudPuffs)
|
||||
{
|
||||
if (puff.transform == null) continue;
|
||||
puff.transform.position = planetCenter + globalRotation * (puff.transform.position - planetCenter);
|
||||
}
|
||||
|
||||
for (int i = 0; i < rainClouds.Count; i++)
|
||||
{
|
||||
RainCloud rc = rainClouds[i];
|
||||
rc.timer -= Time.deltaTime;
|
||||
|
||||
if (rc.isRaining && rc.timer <= 0f)
|
||||
{
|
||||
if (rc.rainInstance != null)
|
||||
Destroy(rc.rainInstance);
|
||||
|
||||
rc.isRaining = false;
|
||||
rc.isFogging = true;
|
||||
rc.timer = 20f;
|
||||
|
||||
Vector3 fogPos = rc.position + (planetCenter - rc.position).normalized * cloudGroupSpread * 1.5f;
|
||||
rc.fogInstance = CreateFog(fogPos);
|
||||
}
|
||||
else if (rc.isFogging && rc.timer <= 0f)
|
||||
{
|
||||
if (rc.fogInstance != null)
|
||||
Destroy(rc.fogInstance);
|
||||
|
||||
rc.isFogging = false;
|
||||
rc.timer = rainPause;
|
||||
|
||||
foreach (CloudPuff puff in rc.puffs)
|
||||
{
|
||||
if (puff.transform != null)
|
||||
Destroy(puff.transform.gameObject);
|
||||
cloudPuffs.Remove(puff);
|
||||
}
|
||||
}
|
||||
else if (!rc.isRaining && !rc.isFogging && rc.timer <= 0f)
|
||||
{
|
||||
foreach (CloudPuff puff in rc.puffs)
|
||||
cloudPuffs.Remove(puff);
|
||||
rainClouds[i] = CreateRainCloud();
|
||||
}
|
||||
|
||||
if (rc.rainInstance != null)
|
||||
rc.rainInstance.transform.position = planetCenter +
|
||||
globalRotation * (rc.rainInstance.transform.position - planetCenter);
|
||||
|
||||
if (rc.fogInstance != null)
|
||||
rc.fogInstance.transform.position = planetCenter +
|
||||
globalRotation * (rc.fogInstance.transform.position - planetCenter);
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyRainCloud(RainCloud rc)
|
||||
{
|
||||
if (rc.rainInstance != null)
|
||||
Destroy(rc.rainInstance);
|
||||
|
||||
foreach (CloudPuff puff in rc.puffs)
|
||||
{
|
||||
if (puff.transform != null)
|
||||
Destroy(puff.transform.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetRainEnabled(bool enabled)
|
||||
{
|
||||
foreach (RainCloud rc in rainClouds)
|
||||
{
|
||||
if (rc.rainInstance != null)
|
||||
rc.rainInstance.SetActive(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCloudsEnabled(bool enabled)
|
||||
{
|
||||
if (cloudRoot != null)
|
||||
cloudRoot.gameObject.SetActive(enabled);
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user