官方定义:
material:
Returns the first instantiated Material assigned to the renderer.
Modifying material
will change the material for this object only.
If the material is used by any other renderers, this will clone the shared material and start using it from now on.
sharedMaterial:
The shared material of this object.
Modifying sharedMaterial
will change the appearance of all objects using this material, and change material settings that are stored in the project too.
It is not recommended to modify materials returned by sharedMaterial. If you want to modify the material of a renderer use material instead.
初始状态:
测试一:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestMaterial : MonoBehaviour {
public GameObject cube;
// Use this for initialization
void Start () {
Renderer cubeRenderer = cube.GetComponent<Renderer>();
GameObject cube1 = Instantiate(cube);
cube1.transform.position = new Vector3(2.0f, 0.0f, 0.0f);
Renderer cube1Renderer = cube1.GetComponent<Renderer>();
if (cubeRenderer.sharedMaterial == cube1Renderer.sharedMaterial)
{
Debug.Log("cube1 sharedMaterial == cube sharedMaterial");
}
else
{
Debug.Log("cube1 sharedMaterial != cube sharedMaterial");
}
//这句调用后,产生变化
cube1Renderer.material.color = Color.blue;
if (cubeRenderer.sharedMaterial == cube1Renderer.sharedMaterial)
{
Debug.Log("cube1 sharedMaterial == cube sharedMaterial");
}
else
{
Debug.Log("cube1 sharedMaterial != cube sharedMaterial");
}
if (cube1Renderer.material == cube1Renderer.sharedMaterial)
{
Debug.Log("cube1 material == cube1 sharedMaterial");
}
else
{
Debug.Log("cube1 material != cube1 sharedMaterial");
}
}
}
结果分析:
Instantiate对象后,cube和cube1的shareMaterial都是一样的,引用的材质都是本地M0。 当调用cube1Renderer.material后,cube和cube1的shareMaterial就不一样了,但是cube1的material和shareMaterial却一样了。根据官方的解释,当调用cube1Renderer.material 后,会根据第一个赋值给renderer的材质实例化一份新的材质出来,这里第一个赋值的材质是M0,所以实例化出来的对象是M0(Instance), 并且此时cube1的material和shareMaterial的值都是M0(Instance).
测试2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestMaterial : MonoBehaviour {
public GameObject cube;
// Use this for initialization
void Start () {
Renderer cubeRenderer = cube.GetComponent<Renderer>();
Material M0 = cubeRenderer.sharedMaterial;
Material M1 = new Material(Shader.Find("Unlit/Color"));
//使用这句的结果和cubeRenderer.sharedMaterial是一样的
//cubeRenderer.material = M1;
cubeRenderer.sharedMaterial = M1;
Material M2 = cubeRenderer.material;
Material M3 = cubeRenderer.sharedMaterial;
if(M1 == M2)
{
Debug.Log("M1 == M2");
}
else
{
Debug.Log("M1 != M2");
}
if (M1 == M3)
{
Debug.Log("M1 == M3");
}
else
{
Debug.Log("M1 != M3");
}
if (M2 == M3)
{
Debug.Log("M2 == M3");
}
else
{
Debug.Log("M2 != M3");
}
}
}
结果分析:
不论使用cubeRenderer.material = M1 还是 cubeRenderer.sharedMaterial = M1; 结果是一样的。 M1都是作为第一个赋值给Renderer的材质,所以调用cubeRenderer.material后,都将生成一个M1的实例出来。
推测出实现方式:
private bool mMaterialChange = true;
//初始材质
private Material mMaterial = new Material(Shader.Find("Default-Material"));
public Material material
{
set
{
mMaterialChange = true;
mMaterial = value;
}
get
{
if(mMaterialChange)
{
mMaterialChange = false;
mMaterial = new Material(mMaterial);
}
return mMaterial;
}
}
public Material sharedMaterial
{
set
{
mMaterialChange = true;
mMaterial = value;
}
get
{
return mMaterial;
}
}