Renderer.sharedMaterial
先上API https://docs.unity3d.com/ScriptReference/Renderer-sharedMaterial.html
返回的是共享材质,当我们改变Renderer.sharedMaterial的时候,所有使用这个材质球的物体都会被改变,并且改变后的设置将会被保存在项目工程中。
一般不推荐使用sharedMaterial去修改,当某个材质球只被一个gameobject使用,或者希望所有用到该材质球的物体同步改变的时候可以使用这个去修改,并且最好在修改之前把原属性设置保存,当使用完毕后立即恢复原设置,防止下次加载的gameobject上还会残留之前的设置信息。
Renderer.material
先上API https://docs.unity3d.com/ScriptReference/Renderer-material.html
返回的是该Renderer第一个实例化后的材质球并赋予当前的Rederer组件。注意这个实例化出来的材质球需要手动销毁或者加载新场景的时候才会自动销毁。
我们第一次使用这个属性会实例化一个新的材质球到内存中,之后再次使用Renderer.material或Renderer. sharedMaterial
都会返回新的那个材质球。
相当于进行了以下操作
GetComponent<Renderer>().material.color = Color.black;
//等同于下列代码
Material lastMat = GetComponent<Renderer>().material;
Material m = Instantiate(lastMat);
GetComponent<Renderer>().material = m;
m.color = Color.black;
经过试验,多次使用Renderer.material,返回的都是第一次实例化的那个Material。
Mat = GetComponent<Renderer>().material;
Mat2 = GetComponent<Renderer>().material;
Debug.Log(object.ReferenceEquals(Mat, Mat2));//返回的是True
Renderer.materials
先上API https://docs.unity3d.com/ScriptReference/Renderer-materials.html
返回的是所有实例化的材质。Unity支持一个Renderer包含多个材质,所以这个属性会返回一个包含该Renderer所有材质的数组。如果不止一个材质,sharedMaterial 和 material属性会返回第一个使用的材质。
使用该属性时,Renderer的所有材质都经过了一次实例化,所以改变材质球只会影响到该物体。
注意:就像Unity返回的所有数组一样,返回的是一个经过复制的数组副本,如果要改变数组中的某些材质,需要重新赋值一个数组给Renderer。(下面会进行测试)
这些实例化的材质也需要手动销毁或者加载新场景的时候自动回收。
直接改变材质数组中某个材质的属性是可以的。
//成功变成黑色
GetComponent<Renderer>().materials[0].color = Color.black;
//成功删除贴图
GetComponent<Renderer>().materials[0].SetTexture("_MainTex", null);
//成功改变shader
GetComponent<Renderer>().materials[0].shader = Shader.Find("Standard");
但是想要更换某个材质球就不行了
//材质数组中的材质没有发生改变
GetComponent<Renderer>().materials[0] = new Material(Shader.Find("Standard"));
正确的赋值方式如下
Material[] matBuff = GetComponent<Renderer>().materials;
matBuff[0] = new Material(Shader.Find("Standard"));//到这一步还不行
GetComponent<Renderer>().materials = matBuff;//必须要赋值回去
//接着测试一下set方法接收的数组是不是副本
matBuff[0] = null;//到这里还不起作用 是副本
GetComponent<Renderer>().materials = matBuff;//还是要赋值回去
所以,Unity返回的是一个新建的数组,然后旧数组的元素逐个赋值给新数组的元素,新旧数组元素的引用都指向同一个材质球,但新数组的元素引用一旦发生改变,旧数组不会受到影响。
另外,可以注意到调用过Renderer.materials属性之后,materials中材质的索引顺序和物体身上显示的材质球顺序是相反的。
UI.Graphic.material
当我们需要在UGUI上使用自定义材质并在运行时改变它时,就要用到material属性,这个属性相当于Renderer.sharedMaterial,返回的是共享材质,当我们希望它只影响一个UI时,就要自己实例化一个材质并赋值给UI。
Material mat = GetComponent<Image>().material;
mat = Instantiate(mat);
GetComponent<Image>().material = mat;
之后就可以直接使用GetComponent<Image>().material或者mat了。