1. 程式人生 > >Unity3d中Material與ShareMaterial引用的區別

Unity3d中Material與ShareMaterial引用的區別

我們在使用Unity引擎的時候,有時候需要去修改某個物體上的Material,在Unity的Renderer類裡,提供了兩個方法介面供我們使用。

Renderer.material和Renderer.sharedMaterial

那麼這兩貨有什麼區別呢!

Renderer.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.

Unity官方文件的解釋是當我們引用修改這個屬性的時候,Unity會返回該Render下第一個例項化後的material賦予當前的Rederer元件。

辣麼,什麼是第一個例項化後的material呢?

Unity中每個MeshRenderer元件裡有個Materals屬性,這個陣列決定了該物體下可以放幾個material元件,預設是1。

當同一個物體上有很多個material的時候,我們可以手動更改material元件的上下位置關係。這裡的**第一個例項化後的material指的就是該物體上從上往下的第一個material元件,而不是Renderer.materials[0]。

cube01.GetComponent<Renderer> ().material.color = Color.black;

上面的程式碼在執行的時候其實是這樣的一個過程:

Material lastMat = cube01.GetComponent<Renderer> ().material;
Material m = Instantiate(lastMat) as Material;
cube01.GetComponent<Renderer> ().material = m;
m.color = Color.black;

也就是說我們每一次引用就會生成一個新的material到記憶體中。但是在引用後並不會改變我們專案工程中材質球的原始屬性設定。

Renderer.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.

當我們改變Renderer.sharedMaterial的時候,所有使用這個材質球物體都會被改變,並且改變後的設定將會被儲存在專案工程中。

官方並不推薦使用這個屬性去修改material。

什麼意思呢?

程式碼解釋:

public GameObject cube01;
public GameObject cube02;
public Material redMat;

假設cube01和cube02共用一個材質redMat,當我們想通過sharedMaterial修改cube01上material的屬性的時候,cube02上對應的屬性也會被修改。

舉個例子:

我們想修改cube01的顏色:

cube01.GetComponent<Renderer> ().sharedMaterial.color = Color.red;

當執行這句程式碼的時候,cube02也會相應的被修改為紅色,而且我們儲存在Project中的材質球也會被持久化的改為紅色。

總結

當使用Renderer.material的時候,每次呼叫都會生成一個新的material到記憶體中去,這在銷燬物體的時候需要我們手動去銷燬該material,否則會一直存在記憶體中。
也可以在場景替換的時候使用Resources.UnloadUnusedAssets去統一釋放記憶體。

當使用Renderer.sharedMaterial的時候並不會生成新的material,而是直接在原material上修改,並且修改後的設定就會被儲存到專案工程中。一般不推薦使用這個去修改,當某個材質球只被一個gameobject使用的時候可以使用這個去修改,並且最好在修改之前把原屬性設定儲存,當使用完畢後立即恢復原設定,防止下次載入後的gameobject上還會殘留之前的設定資訊。

如果是主角這一類gameobject身上需要修改材質的屬性或者shader屬性比較多的時候,可以第一次使用material,這樣可以動態的生成一個material例項,然後再使用sharedmaterial,動態的修改這個新生成的material,而且不會建立新的material。