Repository navigation
Expand file tree
/
Copy pathSeaSplashSystem.cs
More file actions
161 lines (161 loc) · 7.87 KB
/
Copy pathSeaSplashSystem.cs
File metadata and controls
161 lines (161 loc) · 7.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
using UnityEngine;
namespace NuclearRain
{
public class SeaSplashSystem
{
private const float CrownAFrameStart = 0f / 24f;
private const float CrownAFrameEnd = 7f / 24f;
private const float CrownBFrameStart = 8f / 24f;
private const float CrownBFrameEnd = 15f / 24f;
private const float PlateFrameStart = 16f / 24f;
private const float PlateFrameEnd = 23f / 24f;
private const float Rate = 2400f;
private const float Radius = 200f;
private const float MaxAlt = 250f;
private const float ProbeDown = 400f;
private const int MaxPerFrame = 50;
private const float SizeMin = 1.4f, SizeMax = 3.2f;
private const float CrownScale = 0.6f;
private const float LifeMin = 0.45f, LifeMax = 0.7f;
private readonly ParticleSystem _plate;
private readonly ParticleSystem _crownA;
private readonly ParticleSystem _crownB;
private readonly Material _matPlate;
private readonly Material _matCrownA;
private readonly Material _matCrownB;
private float _budget;
public SeaSplashSystem(Texture2D sheet, Transform parent)
{
sheet.wrapMode = TextureWrapMode.Clamp;
_plate = Build(sheet, parent, "SeaSplashPlate",
ParticleSystemRenderMode.HorizontalBillboard,
PlateFrameStart, PlateFrameEnd, out _matPlate);
_crownA = Build(sheet, parent, "SeaSplashCrownA",
ParticleSystemRenderMode.VerticalBillboard,
CrownAFrameStart, CrownAFrameEnd, out _matCrownA);
_crownB = Build(sheet, parent, "SeaSplashCrownB",
ParticleSystemRenderMode.VerticalBillboard,
CrownBFrameStart, CrownBFrameEnd, out _matCrownB);
}
public void Update(float dt, Vector3 camPos, float intensity, float alpha, float dayNight)
{
float a = Mathf.Clamp01(alpha * 2.5f);
Color tintP = new Color(0.85f * dayNight, 0.9f * dayNight, 1f * dayNight, a);
if (_matPlate != null) _matPlate.color = tintP;
if (_matCrownA != null) _matCrownA.color = tintP;
if (_matCrownB != null) _matCrownB.color = tintP;
if (intensity <= 0.01f) { _budget = 0f; return; }
DatumSpace.Bind(_plate); DatumSpace.Bind(_crownA); DatumSpace.Bind(_crownB);
float groundDist;
if (Physics.Raycast(camPos, Vector3.down, out RaycastHit ground,
ProbeDown, Physics.DefaultRaycastLayers,
QueryTriggerInteraction.Collide))
{
groundDist = ground.distance;
}
else
{
groundDist = camPos.y - Datum.LocalSeaY;
if (groundDist < 0f) { _budget = 0f; return; }
}
float altFade = Mathf.Clamp01(1f - groundDist / MaxAlt);
if (altFade <= 0f) { _budget = 0f; return; }
_budget += Rate * intensity * altFade * dt;
int spawned = 0;
while (_budget >= 1f && spawned < MaxPerFrame)
{
_budget -= 1f;
spawned++;
Vector2 r = UnityEngine.Random.insideUnitCircle * Radius;
Vector3 origin = new Vector3(camPos.x + r.x, camPos.y, camPos.z + r.y);
RainRaycast.TryFindGround(origin, ProbeDown, out Vector3 land, out bool isWater);
if (!isWater) continue;
float size = UnityEngine.Random.Range(SizeMin, SizeMax);
float life = UnityEngine.Random.Range(LifeMin, LifeMax);
var plateEp = new ParticleSystem.EmitParams
{
position = DatumSpace.ToDatum(land),
velocity = Vector3.zero,
rotation = UnityEngine.Random.Range(0f, 360f),
startSize = size,
startLifetime = life
};
_plate.Emit(plateEp, 1);
var crownEp = plateEp;
crownEp.rotation = 0f;
crownEp.startSize = size * CrownScale;
if (UnityEngine.Random.value < 0.5f) _crownA.Emit(crownEp, 1);
else _crownB.Emit(crownEp, 1);
}
}
public void SetActive(bool on)
{
if (_plate != null) _plate.gameObject.SetActive(on);
if (_crownA != null) _crownA.gameObject.SetActive(on);
if (_crownB != null) _crownB.gameObject.SetActive(on);
}
public void Dispose()
{
if (_plate != null) Object.Destroy(_plate.gameObject);
if (_crownA != null) Object.Destroy(_crownA.gameObject);
if (_crownB != null) Object.Destroy(_crownB.gameObject);
if (_matPlate != null) Object.Destroy(_matPlate);
if (_matCrownA != null) Object.Destroy(_matCrownA);
if (_matCrownB != null) Object.Destroy(_matCrownB);
}
private static ParticleSystem Build(Texture2D sheet, Transform parent, string name,
ParticleSystemRenderMode mode,
float frameStart, float frameEnd, out Material mat)
{
var go = new GameObject(name);
go.transform.SetParent(parent, false);
var ps = go.AddComponent<ParticleSystem>();
ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
var main = ps.main;
main.startSpeed = 0f;
main.maxParticles = 2000;
main.simulationSpace = ParticleSystemSimulationSpace.World;
main.playOnAwake = true;
var emission = ps.emission;
emission.rateOverTime = 0f;
var shape = ps.shape;
shape.enabled = false;
var tsa = ps.textureSheetAnimation;
tsa.enabled = true;
tsa.numTilesX = 8;
tsa.numTilesY = 3;
tsa.cycleCount = 1;
tsa.frameOverTime = new ParticleSystem.MinMaxCurve(1f,
AnimationCurve.Linear(0f, frameStart, 1f, frameEnd));
var r = go.GetComponent<ParticleSystemRenderer>();
r.renderMode = mode;
if (mode == ParticleSystemRenderMode.VerticalBillboard)
r.pivot = new Vector3(0f, 0.4f, 0f);
r.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
r.receiveShadows = false;
mat = MakeFlipbookMaterial(sheet);
r.sharedMaterial = mat;
DatumSpace.Bind(ps);
ps.Play();
return ps;
}
private static Material MakeFlipbookMaterial(Texture2D tex)
{
Shader sh = Shader.Find("Universal Render Pipeline/Particles/Unlit")
?? Shader.Find("Universal Render Pipeline/Unlit")
?? Shader.Find("Sprites/Default");
if (sh == null) sh = Shader.Find("Diffuse");
var m = new Material(sh) { renderQueue = 3100 };
string texProp = m.HasProperty("_BaseMap") ? "_BaseMap" : "_MainTex";
m.SetTexture(texProp, tex);
if (m.HasProperty("_Surface")) m.SetFloat("_Surface", 1f);
if (m.HasProperty("_Blend")) m.SetFloat("_Blend", 0f);
m.SetOverrideTag("RenderType", "Transparent");
m.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
m.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
m.SetInt("_ZWrite", 0);
m.EnableKeyword("_ALPHABLEND_ON");
return m;
}
}
}