Renderer.materials
is a getter that returns a copy of the materials array.
The code you've written modifies that copy, but does not change the material used by the object, which is why it always shows up as the default.
What you want to do instead is something like the following:
var renderer = GetComponent<Renderer>();
var materials = renderer.sharedMaterials;
materials[0] = Resources.Load<Material>("Test");
renderer.sharedMaterials = materials;
or, if you only have one material on the object, you can take a shortcut:
renderer.sharedMaterial = Resources.Load<Material>("Test");
One detail of note:
In these examples I chose to use sharedMaterials
/sharedMaterial
, which are slightly different getter/setter properties. materials
/material
do a deep copy, in that they create a unique instance of the materials they return.
This means if I have 10 cubes using the "red" material, then I say cube5.renderer.material.color = Color.Blue
, only the one cube will change colour - it has a unique copy of the material now, which is separate from the red material used by all the others.
If I instead say cube5.renderer.sharedMaterial.color = Color.Blue
then all my red cubes will turn blue, because I've modified the single material instance they're all sharing.
This fact about hidden material copying is useful to keep in mind, since materials aren't garbage collected as readily as certain other objects. You want to make sure you know when you're creating a new instance of a material versus when you're modifying an existing (and possibly shared) instance.