Editing ParticleSystem.main's Values Via Script

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)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldarg.0

  //  This grabs that ParticleSystem reference
  IL_0002:  ldfld      class UnityEngine.ParticleSystem UnityEngine.ParticleSystem/MainModule::m_ParticleSystem
  IL_0007:  ldarg.1

  // This calls another function, which operates on the ParticleSystem, not MainModule
  IL_0008:  call       void UnityEngine.ParticleSystem/MainModule::SetLoop(class UnityEngine.ParticleSystem,
  IL_000d:  ret
} // end of method MainModule::set_loop