Did you find it? Here’s a clue: It starts off as the lowest line and ends up not being the lowest one… Yup. That strange burnt ochre that shows how many materials there are currently. The key here is that this is (pretty much) normal gameplay (apart from me spamming a specific game event) and the number of actual game objects stays relatively constant throughout. That big spike in the blue texture memory line? That’s what happens when you cast a fireball.
During the game, you’d expect the material count to climb, but only as much as there were new objects on the screen. Unfortunately they keep slowly, inexorably, climbing every time something happens. That something is a new particle effect being created. Figuring that out was pretty easy – as was figuring out where the material was being leaked: Unity will clone a material every time you reference a GameObject’s renderer.material property. It assumes that you intend to change this particular material in some way, so in order to not change every object of that type, it gives that specific instance a unique material. The problem comes in when Unity prevents materials being handled by standard garbage collection.
Generally, this pessimistic approach is fine. We’d been bitten by this sort of reference-loss problem before, but for some reason in the case of particle systems, an extra clone of an otherwise brand-spanking new material was being created, which we weren’t holding on to and thus was being leaked into the ether of graphics memory where it would be useless to everyone. Eventually, at some hideous time, I stumbled on the right order of operations to prevent this superfluous material’s creation. So now that burnt ochre bloody-well stays put.
Also, the game should be slightly faster and not do that thing where it crashes after you run it nonstop for 3 years… It was a really small memory leak and modern PCs have a lot of room.