2
\$\begingroup\$

The goal is to remove the particles via script with fade effect. But I'm not just interested in an alternative, I want to understand why my code doesn't work.

The code below is modified to show only the important parts. I can't know before what time the particles will be dissolved, so I can't set the parameter from the editor.

StarsConfig.Stars.colorOverLifetime.color.gradient.SetKeys This is the important point (see the log image). The gradient does not take my new values but alphaKey is correct.

Why ? Thanks

private bool FadeStarts = false;

void Update()
{
    if (FadeStarts) return;
    StartCoroutine(fadeStars(false));
}


private IEnumerator fadeStars(bool show)
{

    FadeStarts = true;

    ParticleSystem.ColorOverLifetimeModule c = new ParticleSystem.ColorOverLifetimeModule();

    c = StarsConfig.Stars.colorOverLifetime;

    Gradient g = c.color.gradient;

    Debug.Log("OFF " + c.color.gradient.alphaKeys[0].alpha + " --> " + g.alphaKeys[0].alpha);

    GradientAlphaKey[] alphaKey = new GradientAlphaKey[2];
    alphaKey[0] = c.color.gradient.alphaKeys[0];
    alphaKey[1] = c.color.gradient.alphaKeys[1];


    while (c.color.gradient.alphaKeys[0].alpha > 0f) {

        alphaKey[0].alpha -= StarsConfig.VelocityAlpha * Time.deltaTime;
        alphaKey[1].alpha -= StarsConfig.VelocityAlpha * Time.deltaTime;

        StarsConfig.Stars.colorOverLifetime.color.gradient.SetKeys(c.color.gradient.colorKeys, alphaKey);

        Debug.Log("g " + alphaKey[0].alpha + " --> " + StarsConfig.Stars.colorOverLifetime.color.gradient.alphaKeys[0].alpha);

        /*
        StarsConfig.Stars.colorOverLifetime.color.gradient.SetKeys(
            new GradientColorKey[] { new GradientColorKey(Color.white, 0f),
                                    new GradientColorKey(Color.white, 1.0f) },
            new GradientAlphaKey[] { new GradientAlphaKey(StarsConfig.Stars.colorOverLifetime.color.gradient.alphaKeys[0].alpha - (StarsConfig.VelocityAlpha * Time.deltaTime), 0f),
                                    new GradientAlphaKey(StarsConfig.Stars.colorOverLifetime.color.gradient.alphaKeys[1].alpha - (StarsConfig.VelocityAlpha * Time.deltaTime), 1f) });

        */

        yield return 0;
    }

    StarsConfig.Stars.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);


    FadeStarts = false;
}

enter image description here

UPDATE

Ed_Marty's suggestion is correct, and the solution is there (thanks!). But I would like to understand what is the difference between these two codes.

This code works

var col = StarsConfig.Stars.colorOverLifetime;
while (col.color.gradient.alphaKeys[0].alpha > 0f) {

    float alpha = StarsConfig.Stars.colorOverLifetime.color.gradient.alphaKeys[0].alpha - (StarsConfig.VelocityAlpha * Time.deltaTime);

    Gradient grad = new Gradient();
    grad.SetKeys(
        new GradientColorKey[] {
            new GradientColorKey(Color.white, 0.0f),
            new GradientColorKey(Color.white, 1.0f) }, 
        new GradientAlphaKey[] {
            new GradientAlphaKey(alpha, 0.0f),
            new GradientAlphaKey(alpha, 1.0f) });

    col.color = grad;

    yield return 0;
}

And this doesn't work

while (StarsConfig.Stars.colorOverLifetime.color.gradient.alphaKeys[0].alpha > 0f) {

    float alpha = StarsConfig.Stars.colorOverLifetime.color.gradient.alphaKeys[0].alpha - (StarsConfig.VelocityAlpha * Time.deltaTime);

    StarsConfig.Stars.colorOverLifetime.color.gradient.SetKeys(
        new GradientColorKey[] { new GradientColorKey(Color.white, 0f),
                                 new GradientColorKey(Color.white, 1.0f) },
        new GradientAlphaKey[] { new GradientAlphaKey(alpha, 0f),
                                 new GradientAlphaKey(alpha, 1f) });

    yield return 0;
}
\$\endgroup\$
4
  • \$\begingroup\$ Have you tried doing it how the docs recommend? docs.unity3d.com/ScriptReference/… \$\endgroup\$ – Ed Marty May 26 '19 at 14:55
  • \$\begingroup\$ Yes, if you check my code I created a Gradient g but I don't use it, because it has remained from the previous tests. \$\endgroup\$ – Baro May 26 '19 at 14:59
  • 1
    \$\begingroup\$ I mean specifically how they fetch the component and assign the gradient and color separately. You’re doing it all in one line. \$\endgroup\$ – Ed Marty May 26 '19 at 15:21
  • \$\begingroup\$ @EdMarty Thank you very much, you helped me to solve, if now someone explains to me the difference between the two codes I would be grateful :) \$\endgroup\$ – Baro May 26 '19 at 16:25
3
\$\begingroup\$

ColorOverLifetimeModule.color is a property getter that returns a copy of the MinMaxGradient struct's values.

So your first earlier code StarsConfig.Stars.colorOverLifetime.color.gradient.SetKeys(...) takes this copy, and modified the copy... then discards it. Since you were modifying the copy, your particle system's original values remain unchanged.

The magic line in the new code is col.color = grad, which takes the modified gradient you've made and hands it back to the module to update its internal state.

\$\endgroup\$
6
  • \$\begingroup\$ How does it hand back? ColorOverLifetimeModule is a struct as well, so we copy it to the col and that's ok, but we never put it back to the StarsConfig.Stars.colorOverLifetime and it still works. Why? \$\endgroup\$ – Sergey Nov 22 '20 at 19:20
  • \$\begingroup\$ There's nothing that would prevent ColorOverLifetimeModule from storing a reference to its source particle system, to communicate back to it after you modify its properties. \$\endgroup\$ – DMGregory Nov 22 '20 at 19:26
  • \$\begingroup\$ Ok, thanks! I see it now in source code, the struct definition from meta is not full. Still quite an unusual pattern for me in C#. \$\endgroup\$ – Sergey Nov 22 '20 at 19:34
  • \$\begingroup\$ Why might this code not work? ................ ColorOverLifetimeModule colorOverLifetime = _particle.colorOverLifetime; MinMaxGradient color = colorOverLifetime.color; color.gradient.colorKeys[1] = new GradientColorKey(new Color(1, 0, 0), 0.5f); colorOverLifetime.color = color; \$\endgroup\$ – Sergey Nov 22 '20 at 20:04
  • \$\begingroup\$ Sounds like you have a new Question you can post by clicking the "Ask Question" button. \$\endgroup\$ – DMGregory Nov 22 '20 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.