Use case for Renderer.materials vs sharedMaterials?

As the docs say for Renderer.materials “this function automatically instantiates the materials and makes them unique to this renderer.”.
sharedMaterials does not instantiate the materials.

If you need to make some (or all even) of the materials unique to a renderer, then you can still use sharedMaterials to get/set the array of materials and then you can assign an edited version of a material if required to some of the material slots, but keep others shared where it makes sense.
Although the doc says “Modifying any material in sharedMaterials will change the appearance of all objects using this material,” that does not mean you can’t replace the material entirely with an instanced version of any material.

So does the .materials call just make it easier to mistakenly instance all of a renderer’s materials by using it instead of sharedMaterials, or is it genuinely useful to have these 2 materials calls?

Kind of an odd question… it is just how the API is.

In the past made the classic mistake of not understanding it when I first used it.

But now I can see that the way it works is pretty analogous to a lot of other Unity-engine-side stuff that gets exposed through the C# API.

yeah, it is what it is - but I noticed some old code making the mistake of using materials not sharedMaterials, so I thought maybe it would have been better not to have the materials with instantiation at all. But as always - understand it and it will do…
One API was a common old tween library that instantiated materials every time it changed a color in a tween so… common mistake perhaps.

These APIs also have roots going waaaaay back… I bet Unity started with just a .material and then went to .materials, then at some point needed the .shared* equivalents.

But yeah, it does commonly cause mistakes. Not only that but over time the API continues to evolve and actual behaviors change in subtle ways.

For random example, it used to be acceptable to call CharacterController.Move() twice in one frame, but if you do that now, the grounded check can fail. But… the Unity example code still shows calling it two times per frame. You’re welcome to report the problem too, as I have already done so a few times. :slight_smile:

Note how the example code above calls .Move() twice, and FAILS to properly ground check, whereas it used to in the past.

But I digress.

1 Like

They should also move on from Mathf, now that we have proper MathF. Almost all functions in Mathf are 64-bit System.Math functions casting from float to double and back in disguise. I shiver just by thinking about Mathf.Sqrt and Sin/Cos.