1 using UnityEngine;
2 using
System.Collections;
3
4 /*
5
6     Detonator - A parametric explosion system
for Unity
7     Created
by Ben Throop in August 2009 for the Unity Summer of Code
8     
9     Simplest use
case:
10     
11     
1) Use a prefab
12     
13     OR
14     
15     
1) Attach a Detonator to a GameObject, either through code or the Unity UI
16     
2) Either set the Detonator's ExplodeOnStart = true or call Explode() yourself when the time is right
17     
3) View explosion :)
18     
19     Medium Complexity Use Case:
20     
21     
1) Attach a Detonator as above
22     
2) Change parameters, add your own materials, etc
23     
3) Explode()
24     
4) View Explosion
25     
26     Super Fun Use Case:
27     
28     
1) Attach a Detonator as above
29     
2) Drag one or more DetonatorComponents to that same GameObject
30     
3) Tweak those parameters
31     
4) Explode()
32     
5) View Explosion
33     
34     Better documentation
is included as a PDF with this package, or is available online. Check the Unity site for a link
35     or visit my site, listed below.
36     
37     Ben Throop
38     @ben_throop
39 */
40
41 [AddComponentMenu(
"Detonator/Detonator")]
42 public
class Detonator : MonoBehaviour {
43
44     
private static float _baseSize = 30f;
45     
private static Color _baseColor = new Color(1f, .423f, 0f, .5f);
46     
private static float _baseDuration = 3f;
47     
48     
/*
49         _baseSize reflects the size that DetonatorComponents at size
1 match. Yes, this is really big (30m)
50         size below
is the default Detonator size, which is more reasonable for typical useage.
51         It wasn
't my intention for them to be different, and I may change that, but for now, that's how it is.
52     */

53     
public float size = 10f;
54     
public Color color = Detonator._baseColor;
55     
public bool explodeOnStart = true;
56     
public float duration = Detonator._baseDuration;
57     
public float detail = 1f;
58     
public float upwardsBias = 0f;
59     
60     
public float destroyTime = 7f; //sorry this is not auto calculated... yet.
61     
public bool useWorldSpace = true;
62     
public Vector3 direction = Vector3.zero;
63     
64     
public Material fireballAMaterial;
65     
public Material fireballBMaterial;
66     
public Material smokeAMaterial;
67     
public Material smokeBMaterial;
68     
public Material shockwaveMaterial;
69     
public Material sparksMaterial;
70     
public Material glowMaterial;
71     
public Material heatwaveMaterial;
72         
73     
private Component[] components;
74
75     
private DetonatorFireball _fireball;
76     
private DetonatorSparks _sparks;
77     
private DetonatorShockwave _shockwave;
78     
private DetonatorSmoke _smoke;
79     
private DetonatorGlow _glow;
80     
private DetonatorLight _light;
81     
private DetonatorForce _force;
82     
private DetonatorHeatwave _heatwave;
83     
public bool autoCreateFireball = true;
84     
public bool autoCreateSparks = true;
85     
public bool autoCreateShockwave = true;
86     
public bool autoCreateSmoke = true;
87     
public bool autoCreateGlow = true;
88     
public bool autoCreateLight = true;
89     
public bool autoCreateForce = true;
90     
public bool autoCreateHeatwave = false;
91     
92     
void Awake()
93     {
94         FillDefaultMaterials();
95         
96         components =
this.GetComponents(typeof(DetonatorComponent));
97         
foreach (DetonatorComponent dc in components)
98         {
99             
if (dc is DetonatorFireball)
100             {
101                 _fireball = dc
as DetonatorFireball;
102             }
103             
if (dc is DetonatorSparks)
104             {
105                 _sparks = dc
as DetonatorSparks;
106             }
107             
if (dc is DetonatorShockwave)
108             {
109                 _shockwave = dc
as DetonatorShockwave;
110             }
111             
if (dc is DetonatorSmoke)
112             {
113                 _smoke = dc
as DetonatorSmoke;
114             }
115             
if (dc is DetonatorGlow)
116             {
117                 _glow = dc
as DetonatorGlow;
118             }
119             
if (dc is DetonatorLight)
120             {
121                 _light = dc
as DetonatorLight;
122             }
123             
if (dc is DetonatorForce)
124             {
125                 _force = dc
as DetonatorForce;
126             }
127             
if (dc is DetonatorHeatwave)
128             {
129                 _heatwave = dc
as DetonatorHeatwave;
130             }
131         }
132         
133         
if (!_fireball && autoCreateFireball)
134         {
135             _fireball = gameObject.AddComponent<DetonatorFireball>()
as DetonatorFireball;
136             _fireball.Reset();
137         }
138         
139         
if (!_smoke && autoCreateSmoke)
140         {
141             _smoke = gameObject.AddComponent<DetonatorSmoke>()
as DetonatorSmoke;
142             _smoke.Reset();
143         }
144         
145         
if (!_sparks && autoCreateSparks)
146         {
147             _sparks = gameObject.AddComponent<DetonatorSparks>()
as DetonatorSparks;
148             _sparks.Reset();
149         }
150         
151         
if (!_shockwave && autoCreateShockwave)
152         {
153             _shockwave = gameObject.AddComponent<DetonatorShockwave>()
as DetonatorShockwave;
154             _shockwave.Reset();
155         }
156         
157         
if (!_glow && autoCreateGlow)
158         {
159             _glow = gameObject.AddComponent<DetonatorGlow>()
as DetonatorGlow;
160             _glow.Reset();
161         }
162         
163         
if (!_light && autoCreateLight)
164         {
165             _light = gameObject.AddComponent<DetonatorLight>()
as DetonatorLight;
166             _light.Reset();
167         }
168         
169         
if (!_force && autoCreateForce)
170         {
171             _force = gameObject.AddComponent<DetonatorForce>()
as DetonatorForce;
172             _force.Reset();
173         }
174
175         
if (!_heatwave && autoCreateHeatwave && SystemInfo.supportsImageEffects)
176         {
177             _heatwave = gameObject.AddComponent<DetonatorHeatwave>()
as DetonatorHeatwave;
178             _heatwave.Reset();
179         }
180         
181         components =
this.GetComponents(typeof(DetonatorComponent));
182     }
183     
184     
void FillDefaultMaterials()
185     {
186         
if (!fireballAMaterial) fireballAMaterial = DefaultFireballAMaterial();
187         
if (!fireballBMaterial) fireballBMaterial = DefaultFireballBMaterial();
188         
if (!smokeAMaterial) smokeAMaterial = DefaultSmokeAMaterial();
189         
if (!smokeBMaterial) smokeBMaterial = DefaultSmokeBMaterial();
190         
if (!shockwaveMaterial) shockwaveMaterial = DefaultShockwaveMaterial();
191         
if (!sparksMaterial) sparksMaterial = DefaultSparksMaterial();
192         
if (!glowMaterial) glowMaterial = DefaultGlowMaterial();
193         
if (!heatwaveMaterial) heatwaveMaterial = DefaultHeatwaveMaterial();
194     }
195     
196     
void Start()
197     {
198         
if (explodeOnStart)
199         {
200             UpdateComponents();
201             
this.Explode();
202         }
203     }
204     
205     
private float _lastExplosionTime = 1000f;
206     
void Update ()
207     {
208         
if (destroyTime > 0f)
209         {
210             
if (_lastExplosionTime + destroyTime <= Time.time)
211             {
212                 Destroy(gameObject);
213             }
214         }
215     }
216     
217     
private bool _firstComponentUpdate = true;
218
219     
void UpdateComponents()
220     {
221         
if (_firstComponentUpdate)
222         {
223             
foreach (DetonatorComponent component in components)
224             {
225                 component.Init();
226                 component.SetStartValues();
227             }
228             _firstComponentUpdate =
false;
229         }
230         
231         
if (!_firstComponentUpdate)
232         {
233             
float s = size / _baseSize;
234             
235             Vector3 sdir =
new Vector3(direction.x * s, direction.y * s, direction.z * s);
236             
237             
float d = duration / _baseDuration;
238             
239             
foreach (DetonatorComponent component in components)
240             {
241                 
if (component.detonatorControlled)
242                 {
243                     component.size = component.startSize * s;
244                     component.timeScale = d;
245                     component.detail = component.startDetail * detail;
246                     component.force =
new Vector3(component.startForce.x * s + sdir.x, component.startForce.y * s + sdir.y, component.startForce.z * s + sdir.z );
247                     component.velocity =
new Vector3(component.startVelocity.x * s + sdir.x, component.startVelocity.y * s + sdir.y, component.startVelocity.z * s + sdir.z );
248                     
249                     
//take the alpha of detonator color and consider it a weight - 1=use all detonator, 0=use all components
250                     component.color = Color.Lerp(component.startColor, color, color.a);
251                 }
252             }
253         }
254     }
255     
256     
private Component[] _subDetonators;
257     
258      
public void Explode()
259     {
260         _lastExplosionTime = Time.time;
261     
262         
foreach (DetonatorComponent component in components)
263         {
264             UpdateComponents();
265             component.Explode();
266         }
267     }
268     
269     
public void Reset()
270     {
271         size =
10f; //this is hardcoded because _baseSize up top is not really the default as much as what we match to
272         color = _baseColor;
273         duration = _baseDuration;
274         FillDefaultMaterials();
275     }
276     
277
278     
//Default Materials
279     
//The statics are so that even if there are multiple Detonators in the world, they
280     
//don't each create their own default materials. Theoretically this will reduce draw calls, but I haven't really
281     
//tested that.
282     
public static Material defaultFireballAMaterial;
283     
public static Material defaultFireballBMaterial;
284     
public static Material defaultSmokeAMaterial;
285     
public static Material defaultSmokeBMaterial;
286     
public static Material defaultShockwaveMaterial;
287     
public static Material defaultSparksMaterial;
288     
public static Material defaultGlowMaterial;
289     
public static Material defaultHeatwaveMaterial;
290     
291     
public static Material DefaultFireballAMaterial()
292     {
293         
if (defaultFireballAMaterial != null) return defaultFireballAMaterial;
294         defaultFireballAMaterial =
new Material(Shader.Find("Particles/Additive"));
295         defaultFireballAMaterial.name =
"FireballA-Default";
296         Texture2D tex = Resources.Load(
"Detonator/Textures/Fireball") as Texture2D;
297         defaultFireballAMaterial.SetColor(
"_TintColor", Color.white);
298         defaultFireballAMaterial.mainTexture = tex;
299         defaultFireballAMaterial.mainTextureScale =
new Vector2(0.5f, 1f);
300         
return defaultFireballAMaterial;
301     }
302
303     
public static Material DefaultFireballBMaterial()
304     {
305         
if (defaultFireballBMaterial != null) return defaultFireballBMaterial;
306         defaultFireballBMaterial =
new Material(Shader.Find("Particles/Additive"));
307         defaultFireballBMaterial.name =
"FireballB-Default";
308         Texture2D tex = Resources.Load(
"Detonator/Textures/Fireball") as Texture2D;
309         defaultFireballBMaterial.SetColor(
"_TintColor", Color.white);
310         defaultFireballBMaterial.mainTexture = tex;
311         defaultFireballBMaterial.mainTextureScale =
new Vector2(0.5f, 1f);
312         defaultFireballBMaterial.mainTextureOffset =
new Vector2(0.5f, 0f);
313         
return defaultFireballBMaterial;
314     }
315     
316     
public static Material DefaultSmokeAMaterial()
317     {
318         
if (defaultSmokeAMaterial != null) return defaultSmokeAMaterial;
319         defaultSmokeAMaterial =
new Material(Shader.Find("Particles/Alpha Blended"));
320         defaultSmokeAMaterial.name =
"SmokeA-Default";
321         Texture2D tex = Resources.Load(
"Detonator/Textures/Smoke") as Texture2D;
322         defaultSmokeAMaterial.SetColor(
"_TintColor", Color.white);
323         defaultSmokeAMaterial.mainTexture = tex;
324         defaultSmokeAMaterial.mainTextureScale =
new Vector2(0.5f, 1f);
325         
return defaultSmokeAMaterial;
326     }
327         
328     
public static Material DefaultSmokeBMaterial()
329     {
330         
if (defaultSmokeBMaterial != null) return defaultSmokeBMaterial;
331         defaultSmokeBMaterial =
new Material(Shader.Find("Particles/Alpha Blended"));
332         defaultSmokeBMaterial.name =
"SmokeB-Default";
333         Texture2D tex = Resources.Load(
"Detonator/Textures/Smoke") as Texture2D;
334         defaultSmokeBMaterial.SetColor(
"_TintColor", Color.white);
335         defaultSmokeBMaterial.mainTexture = tex;
336         defaultSmokeBMaterial.mainTextureScale =
new Vector2(0.5f, 1f);
337         defaultSmokeBMaterial.mainTextureOffset =
new Vector2(0.5f, 0f);
338         
return defaultSmokeBMaterial;
339     }
340     
341     
public static Material DefaultSparksMaterial()
342     {
343         
if (defaultSparksMaterial != null) return defaultSparksMaterial;
344         defaultSparksMaterial =
new Material(Shader.Find("Particles/Additive"));
345         defaultSparksMaterial.name =
"Sparks-Default";
346         Texture2D tex = Resources.Load(
"Detonator/Textures/GlowDot") as Texture2D;
347         defaultSparksMaterial.SetColor(
"_TintColor", Color.white);
348         defaultSparksMaterial.mainTexture = tex;
349         
return defaultSparksMaterial;
350     }
351     
352     
public static Material DefaultShockwaveMaterial()
353     {
354         
if (defaultShockwaveMaterial != null) return defaultShockwaveMaterial;
355         defaultShockwaveMaterial =
new Material(Shader.Find("Particles/Additive"));
356         defaultShockwaveMaterial.name =
"Shockwave-Default";
357         Texture2D tex = Resources.Load(
"Detonator/Textures/Shockwave") as Texture2D;
358         defaultShockwaveMaterial.SetColor(
"_TintColor", new Color(0.1f,0.1f,0.1f,1f));
359         defaultShockwaveMaterial.mainTexture = tex;
360         
return defaultShockwaveMaterial;
361     }
362     
363     
public static Material DefaultGlowMaterial()
364     {
365         
if (defaultGlowMaterial != null) return defaultGlowMaterial;
366         defaultGlowMaterial =
new Material(Shader.Find("Particles/Additive"));
367         defaultGlowMaterial.name =
"Glow-Default";
368         Texture2D tex = Resources.Load(
"Detonator/Textures/Glow") as Texture2D;
369         defaultGlowMaterial.SetColor(
"_TintColor", Color.white);
370         defaultGlowMaterial.mainTexture = tex;
371         
return defaultGlowMaterial;
372     }
373     
374     
public static Material DefaultHeatwaveMaterial()
375     {
376         
//Unity Pro Only
377         
if (SystemInfo.supportsImageEffects)
378         {
379             
if (defaultHeatwaveMaterial != null) return defaultHeatwaveMaterial;
380             defaultHeatwaveMaterial =
new Material(Shader.Find("HeatDistort"));
381             defaultHeatwaveMaterial.name =
"Heatwave-Default";
382             Texture2D tex = Resources.Load(
"Detonator/Textures/Heatwave") as Texture2D;
383             defaultHeatwaveMaterial.SetTexture(
"_BumpMap", tex);
384             
return defaultHeatwaveMaterial;
385         }
386         
else
387         {
388             
return null;
389         }
390     }
391 }