Last active
April 19, 2021 22:14
-
-
Save TobiTobascoNollero/927eb9dc812f86c88421dc5747d86688 to your computer and use it in GitHub Desktop.
Unity - Particle Scaling for Particles inside the Unity GUI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine.UI; | |
/* UI Particle Scaling script by Tobi Tobasco Nollero, questions: [email protected], http://tobiasnoller.com/ | |
* Just drag this script on any canvas which has child particle systems underneath. | |
* Add your resolution change listener to scale your particles when changing resolutions. | |
* Prewarmed particle system emitting on begin play, will probably not be affected by the script the first time they fire. | |
* Feel free to use this script in any project. | |
* If you change/enhance this script, please share your optimizations with the community. | |
*/ | |
[RequireComponent(typeof(Canvas))] | |
public class UIParticleScaler : MonoBehaviour { | |
//The default orthographic size of the gui camera | |
public float refCameraOrthSize = 384f; | |
public bool useCameraOrthSize = false; | |
private Canvas refCanvas; | |
private Camera refCam; | |
private float scale; | |
private ParticleSystem[] particleSystems; | |
private game.gui.menus.OptionsMenu optionsMenu; | |
private float scaleOld = 1f; | |
//Initialization | |
void Start() { | |
// init canvas and camera | |
refCanvas = GetComponent<Canvas>(); | |
refCam = refCanvas.GetComponent<Camera>(); | |
// get particle systems | |
particleSystems = this.gameObject.GetComponentsInChildren<ParticleSystem>(); | |
// add resolution change listener here | |
//optionsMenu = game.gui.menus.OptionsMenu.Instance; | |
//if (optionsMenu != null) | |
// optionsMenu.resChangeListener += StartScaling; | |
// apply scale | |
ApplyScale(); | |
} | |
// ** Delay hack because our resolution change needs some time to change the resolution | |
void StartScaling() { | |
StartCoroutine(StartDelayedScaling()); | |
} | |
IEnumerator StartDelayedScaling() { | |
yield return new WaitForSeconds(0.5f); | |
ApplyScale(); | |
} | |
// ** | |
//Scale all child particle systems | |
public void ApplyScale() { | |
// get new scale | |
float scaleNew = 1f; | |
if (useCameraOrthSize) { | |
if (refCam != null) | |
scaleNew = (refCameraOrthSize / refCam.orthographicSize); | |
} else { | |
scaleNew = refCanvas.transform.localScale.x; | |
} | |
// check to only scale if necessary | |
if (scaleNew == scaleOld) { | |
return; | |
} | |
// scale to 1 | |
scale = (1 / scaleOld); | |
foreach (ParticleSystem p in particleSystems) { | |
if (p != null) | |
ScaleParticleValues(p); | |
} | |
// scale to new scale | |
scale = scaleNew; | |
scaleOld = scaleNew; | |
foreach (ParticleSystem p in particleSystems) { | |
if (p != null) | |
ScaleParticleValues(p); | |
} | |
} | |
//Scale individiual particle system values | |
private void ScaleParticleValues(ParticleSystem ps) { | |
//BASE MODULE | |
var main = ps.main; | |
//StartSize | |
ParticleSystem.MinMaxCurve sSize = main.startSize; | |
main.startSize = MultiplyMinMaxCurve(sSize, scale); | |
//Gravity | |
ParticleSystem.MinMaxCurve sGrav = main.gravityModifier; | |
main.gravityModifier = MultiplyMinMaxCurve(sGrav, scale); | |
//StartSpeed | |
ParticleSystem.MinMaxCurve sSpeed = main.startSpeed; | |
main.startSpeed = MultiplyMinMaxCurve(sSpeed, scale); | |
//MODULES | |
//Shape (divided instead of multiplied) | |
var shape = ps.shape; | |
if (shape.enabled) { | |
shape.radius /= scale; | |
shape.box = shape.box / scale; | |
} | |
//Emisison Rate Time (divided instead of multiplied) | |
ParticleSystem.EmissionModule em = ps.emission; | |
if (em.enabled) { | |
//Time | |
ParticleSystem.MinMaxCurve emRateT = em.rateOverTime; | |
em.rateOverTime = MultiplyMinMaxCurve(emRateT, scale, false); | |
//Distance | |
ParticleSystem.MinMaxCurve emRateD = em.rateOverDistance; | |
em.rateOverDistance = MultiplyMinMaxCurve(emRateD, scale, false); | |
} | |
//Velocities | |
ParticleSystem.VelocityOverLifetimeModule vel = ps.velocityOverLifetime; | |
if(vel.enabled) { | |
vel.x = MultiplyMinMaxCurve(vel.x, scale); | |
vel.y = MultiplyMinMaxCurve(vel.y, scale); | |
vel.z = MultiplyMinMaxCurve(vel.z, scale); | |
} | |
//ClampVelocities | |
ParticleSystem.LimitVelocityOverLifetimeModule clampVel = ps.limitVelocityOverLifetime; | |
if(clampVel.enabled) { | |
clampVel.limitX = MultiplyMinMaxCurve(clampVel.limitX, scale); | |
clampVel.limitY = MultiplyMinMaxCurve(clampVel.limitY, scale); | |
clampVel.limitZ = MultiplyMinMaxCurve(clampVel.limitZ, scale); | |
} | |
//Forces | |
ParticleSystem.ForceOverLifetimeModule force = ps.forceOverLifetime; | |
if (force.enabled) { | |
force.x = MultiplyMinMaxCurve(force.x, scale); | |
force.y = MultiplyMinMaxCurve(force.y, scale); | |
force.z = MultiplyMinMaxCurve(force.z, scale); | |
} | |
} | |
//Multiply or divide ParticleSystem.MinMaxCurve with given value | |
private ParticleSystem.MinMaxCurve MultiplyMinMaxCurve(ParticleSystem.MinMaxCurve curve, float value, bool multiply = true) { | |
if (multiply) { | |
curve.curveMultiplier *= value; | |
curve.constantMin *= value; | |
curve.constantMax *= value; | |
} else { | |
curve.curveMultiplier /= value; | |
curve.constantMin /= value; | |
curve.constantMax /= value; | |
} | |
MultiplyCurveKeys(curve.curveMin, value, multiply); | |
MultiplyCurveKeys(curve.curveMax, value, multiply); | |
return curve; | |
} | |
//Multiply or divide all keys of an AnimationCurve with given value | |
private void MultiplyCurveKeys(AnimationCurve curve, float value, bool multiply = true) { | |
if (curve == null) { return; } | |
if (multiply) | |
for (int i = 0; i < curve.keys.Length; i++) { curve.keys[i].value *= value; } | |
else | |
for (int i = 0; i < curve.keys.Length; i++) { curve.keys[i].value /= value; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment