I’ve been having a lot of trouble editing particlesystem.main’s startColor value in my script. It started with a simple goal in mind, just doing something like
GetComponent<ParticleSystem>().main.startColor = color.blue;
until I got an error saying that it is a read-only value, for a reason I don’t know (but I’m going to assume there’s a reason haha)
I go to Unity documentation and it gives an example like this:
var main = GetComponent<ParticleSystem>().main
main.startColor = new Color();
Now I don’t understand why this would even work. You’re setting main to particlesystem.main to a separate variable, but you aren’t setting the variable back to particlesystem.main, so I don’t understand a use for this…
In any case the code isn’t working for me, but I haven’t tested it much yet so I don’t want to say it doesn’t work at all.
UPDATE: so it does work, but I’m still unsure why this would work.
This surpised me, too. The MainModule struct is indeed a value type and works exactly how you’d expect. The key is that all those exposed members are properties, not fields. A property can be implemented however the author wants, it doesn’t even have to be backed by real data.
Here, Unity has the MainModule struct storing a reference to the ParticleSystem and all the properties operate on that reference. So your local variable gets that same reference, and then all assignments on the properties carry on through to change that ParticleSystem.
I admit I often forget the difference between properties and fields, thinking them both as data members, and that comes back to bite me for situations like this. It didn’t become apparent to me that the property was the key to the magic until looking at Unity’s IL:
.method public hidebysig specialname
instance void set_loop(bool 'value') cil managed
// Code size 14 (0xe)
// This grabs that ParticleSystem reference
IL_0002: ldfld class UnityEngine.ParticleSystem UnityEngine.ParticleSystem/MainModule::m_ParticleSystem
// This calls another function, which operates on the ParticleSystem, not MainModule
IL_0008: call void UnityEngine.ParticleSystem/MainModule::SetLoop(class UnityEngine.ParticleSystem,
} // end of method MainModule::set_loop