ParticleSystem crossed over

When i write smokepuff.particleSystem the particleSystem is crossed out and .startcolor doesnt exist.
Maybe it´s because i use Unity 5.4.1? but in the documentation for 5.4 the .particlesystem is documented.

Hi @LuckieLuuke,

As an example only (variable names may vary);

    public GameObject _destroyedParticles = null;

This is the variable that is exposed via the Inspector for you to drag the smoke prefab onto.

Then in code, within a suitable method;

    GameObject smoke = Instantiate(_destroyedParticles, transform.position, Quaternion.identity) as GameObject;
    smoke.GetComponent<ParticleSystem>().startColor = gameObject.GetComponent<SpriteRenderer>().color; 

Note the startColour here is being set to the color property of the returned SpriteRenderer component, so you will most likely want to change that to something else.

The startColour variable will take a standard Color object.

1 Like

FYI This code no longer works in 5.5.0f3. I get the error:

I used what was suggest by the error in Unity:

smokePuff.GetComponent().main.startColor = gameObject.GetComponent().color;

And I still get an error:

I have had a tough time using this form of Unity 5.5.0f3. I started using it because it was the newest version and so I wanted to become better at the newest version to stay ahead of the curve. I thought it would help me figure things out in the long run but using it has only created a headache and has been very discouraging as a new programmer.

1 Like

There’s an example here:

https://docs.unity3d.com/ScriptReference/ParticleSystem.MainModule-startColor.html

You can’t set main but you can set the startColor variable of it…

ParticleSystem ps = gameObject.GetComponent <ParticleSystem>;

var main = ps.main;
main.startColor = new Color(0, 0, 0, 1);
1 Like

I apologize if this is a dumb question, but why does this work:

ParticleSystem ps = gameObject.GetComponent ;

var main = ps.main;
main.startColor = new Color(0, 0, 0, 1);

But this does not:

ParticleSystem ps = gameObject.GetComponent ;

ps.main.startColor = new Color(0, 0, 0, 1);

When I try to use the option above, I get the error: Cannot modify a value type return value of “UnityEngine.ParticleSystem.main”. Consider storing value in a temporary variable.

I’m still new to C# (coming from javascript), so I’m guessing this is something to do with how C# works?

1 Like

They made it so due to a performance optimization.

The main struct is read-only, whereas sub-structs are read/write, and in order to reach them you need to assign the reference to the main struct to another var.

https://forum.unity3d.com/threads/cant-set-any-new-particle-system-properties-through-script.358964/#post-2326270

1 Like

Okay, I see from the code that ParticleSystem.main is a struct with only a getter.

If I understand C# correctly, when I create a variable and point it at the struct (e.g. var main = ps.main), I am making a copy of the struct. I can then get access to it’s properties because they have setters on them (e.g. main.startColor = new Color()).

But aren’t I working with a copy of the struct vs. a reference? And if I am working with a copy of the struct, how is it impacting the ParticleSystem since I never copy the struct back (e.g. ps.main = main;)?

Thanks for your help!

No, you’re not making a copy, you’re just creating a reference to it, i.e.: they both point at the same actual instance.

Generic example, let’s say you have a class named Box, which has 3 fields and a single constructor:

[code]public class Box {

public float height, width, length;

    public Box(float h, float w, float l) {
        height = h;
        width = w;
        length = l;
    }

}[/code]

Now let’s say you write this class:

[code]public class MyClass {

private Box myBox1, myBox2;

    private void Main(){
        myBox1 = new Box(1,2,3);
        myBox2 = myBox1;
        Console.Writeline(myBox1.height, myBox1.width, myBox1.width);
        Console.Writeline(myBox2.height, myBox2.width, myBox2.width);
    }

}[/code]

In this case you’ll read in the console twice the line “1,2,3”, since myBox2 holds only a reference to myBox1, or, in other words, they both point to the same, single, instance created by the myBox1 = new Box (1,2,3);.
Now, if you add a line before the Writeline like this:

the result in console will be a “2,2,3” twice, because myBox2 points to the same instance of myBox1.

However, if you create two instances with this code:

[code]public class MyClass {

private Box myBox1, myBox2;

    private void Main(){
        myBox1 = new Box(1,2,3);
        myBox2 = new Box(1,2,3);
        myBox2.height = 2;
        Console.Writeline(myBox1.height, myBox1.width, myBox1.width);
        Console.Writeline(myBox2.height, myBox2.width, myBox2.width);
    }

}[/code]
the console will show “1,2,3” in the first line and “2,2,3” in the second line, since now myBox1 and myBox2 hold the reference to two different instances of a Box.

Now, going back to the actual topic at hand, we don’t know what happens under the hood of the Main struct of the Particle System, it may well be that they protect in same way a direct access to its subfields by using main.subfield, but they let it change if we add a reference var to it. This has nothing to do with the fact that Main has only a getter and not a setter, for example the Transform type in Unity has only a getter, but it’s permitted to access its subfields directly without declaring a reference var.

They say it’s because of a performance optimization, we have to make a leap of faith and believe them, being forced to declare the reference var in order to access its subfields, because “they said so”. :smiley:

Thank you for the detailed response. It is really helpful.

I have one clarification question - the objects we’re talking about here are “structs” aren’t they?

And when I read the C# documentation it says, unless I’m misunderstanding, that structs are value types, while classes are reference types.

So when I create a variable that points to a struct, doesn’t it get a copy of that struct vs. a reference?

Oh my, am I dumb. For some reason, while you were talking about a struct, my mind was screaming “CLASSCLASSCLASS” lol.

Now I see your doubt, and it’s indeed legit. I found out that this is true for every struct children of the ParticleSystem class (main, shape, duration, etc., there’re a LOT), and all of them have only a getter.

So the only answer that I can think of at the moment is that, even thou we pass a value when declaring a var like this:

when we access the subfields of myMain, the setter of the subfields pushes up the value we assigned to the MainModule struct, thus protecting it from unexpected behaviour.

If anyone has a better answer, now it’s the time to chime in. :smiley:

1 Like

Your google skills >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> mines. Word.

However, after reading the article, I was almost right about it, they’re pushing up the values of the struct, just directly inside the C++ code of the system.

1 Like

Hehehe… I am one with my Google! :smiley:

1 Like

Privacy & Terms