Unity3DMesh中material和sharedMaterial的區(qū)別及內(nèi)部實(shí)現(xiàn)的推斷是怎樣的

本篇文章為大家展示了Unity3D Mesh中material和sharedMaterial的區(qū)別及內(nèi)部實(shí)現(xiàn)的推斷是怎樣的,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)和政免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了上1000+企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

material 和 sharedMaterial 的區(qū)別

創(chuàng)建一個(gè)Material, 顏色為紅色,
創(chuàng)建兩個(gè)Quad,掛上剛剛創(chuàng)建的材質(zhì)。 效果如下圖:

Unity3D Mesh中material和sharedMaterial的區(qū)別及內(nèi)部實(shí)現(xiàn)的推斷是怎樣的

將第一個(gè)Quad掛載如下腳本, 運(yùn)行:

render = GetComponent<Renderer>();render.material.color = Color.white;

效果如下圖:

Unity3D Mesh中material和sharedMaterial的區(qū)別及內(nèi)部實(shí)現(xiàn)的推斷是怎樣的

修改腳本內(nèi)容如下, 運(yùn)行:

render = GetComponent<Renderer>();render.sharedMaterial.color = Color.white;

Quad的顏色變了
效果如下圖:

Unity3D Mesh中material和sharedMaterial的區(qū)別及內(nèi)部實(shí)現(xiàn)的推斷是怎樣的

如何來(lái)解釋上面的現(xiàn)象呢, 根據(jù)官方文檔

Renderer.sharedMaterial

sharedMaterial 是共用的 Material,稱為共享材質(zhì)。修改共享材質(zhì)會(huì)改變所用使用該材質(zhì)的物體,并且編輯器中的材質(zhì)設(shè)置也會(huì)改變。

Renderer.material

material 是獨(dú)立的 Material,返回分配給渲染器的第一個(gè)材質(zhì)。修改材質(zhì)僅會(huì)改變?cè)撐矬w的材質(zhì)。如果該材質(zhì)被其他的渲染器使用,將克隆該材質(zhì)并用于當(dāng)前的渲染器。


推測(cè) sharedMaterial 和 material 的實(shí)現(xiàn)

下面我們通過(guò)一些實(shí)現(xiàn)猜測(cè) material 是如何實(shí)現(xiàn)的:

我們從 UnityEngine.Renderer 中可得知 sharedMaterial 和 material 是屬性(property),當(dāng)給屬性賦值時(shí)會(huì)隱式的調(diào)用 set 方法,當(dāng)獲取屬性值得時(shí)候會(huì)隱式的調(diào)用 get 方法。假設(shè) sharedMaterial 的值變量假設(shè)為 _sharedMaterial, material 的值變量假設(shè)為 _material。

Material _material;  Material _sharedMaterial;
Material origin_sharedMat = render.sharedMaterial;Debug.Log(origin_sharedMat == render.sharedMaterial);
// True

調(diào)用了 sharedMaterial 的 get方法。 可以推斷出 sharedMaterial 的 get:

return _sharedMaterial;
  • 1

  • 第二個(gè)測(cè)試:

Material new_Mat = new Material(Shader.Find("Standard"));
render.sharedMaterial = new_Mat;Debug.Log(new_Mat == render.sharedMaterial);
// True

調(diào)用了 sharedMaterial 的 set方法。 可以推斷出 sharedMaterial 的 set:

_sharedMaterial = value;
  • 第三個(gè)測(cè)試:

Material origin_sharedMat = render.sharedMaterial;Material origin_Mat = render.material;Debug.Log(origin_sharedMat == render.sharedMaterial);Debug.Log(origin_Mat == render.sharedMaterial); 
Debug.Log(origin_Mat == render.material);
// Flase True True

在隱式調(diào)用 material 的 get 后, sharedMaterial 被修改。且 _material 和 _sharedMaterial 相等。
推斷 material 的 get:

if (_sharedMaterial ~= _material) {
    _material = new Material (_sharedMaterial);//這一步由第四個(gè)測(cè)試共同推出
    _sharedMaterial = _material;

}return _material;
  • 第四個(gè)測(cè)試:

Material new_Mat = new Material(Shader.Find("Standard"));
render.sharedMaterial = new_Mat;Debug.Log(new_Mat == render.sharedMaterial);Material origin_Mat = render.material;Debug.Log(new_Mat == origin_Mat);Debug.Log(origin_Mat == render.sharedMaterial);Debug.Log(origin_Mat == render.material);
// True Flase True True

很明顯 _material的初始化并未通過(guò) material 屬性,因?yàn)槲凑{(diào)用 material 屬性的 get 方法前,_sharedMaterial 和 _material并不相等。
推斷 sharedMaterial 的 set:

_sharedMaterial = value;
  • 第五個(gè)測(cè)試:

Material new_Mat = new Material(Shader.Find("Standard"));render.material = new_Mat;Debug.Log(new_Mat.name);Debug.Log(render.sharedMaterial.name);Debug.Log(render.material.name);// Standard Standard Standard(Instance)

推測(cè) material 的 set:

_sharedMaterial = value;

綜上推斷:

public Material material {  
    get {  
        if (_sharedMaterial ~= _material) {
            _material = new Material (_sharedMaterial);  
            _sharedMaterial = _material;

        }        return _material;  
    }  
    set {          
        _sharedMaterial = value;  
    }  
}public Material sharedMaterial {  
    get {  
        return _sharedMaterial;  
    }  
    set {  
        _sharedMaterial = value;  
    }  
}

使用 material 時(shí)的內(nèi)存泄漏問(wèn)題

每一次引用 Renderer.material 的時(shí)候,都會(huì)生成一個(gè)新的 material 到內(nèi)存中去,銷毀物體的時(shí)候需要我們手動(dòng)去銷毀該material,否則會(huì)一直存在內(nèi)存中。

官方文檔說(shuō):

This function automatically instantiates the materials and makes them unique to this renderer. It is your responsibility to destroy the materials when the game object is being destroyed. Resources.UnloadUnusedAssets also destroys the materials but it is usually only called when loading a new level.

此方法自動(dòng)實(shí)例化該材質(zhì)并且使其成為該渲染器獨(dú)有的材質(zhì)。當(dāng)該游戲物體被刪除時(shí),你應(yīng)該手動(dòng)刪除該材質(zhì)。當(dāng)替換場(chǎng)景調(diào)用 Resources.UnloadUnusedAssets 也可以刪除該材質(zhì)。

編輯器下使用 material, 其他平臺(tái)使用 sharedMaterial

public static Material GetMaterial(Renderer render)  
    {  #if UNITY_EDITOR  
        return render.material;  #else  
        return render.sharedMaterial;  #endif  
    }

如果是主角這一類gameobject身上需要修改材質(zhì)的屬性或者shader屬性比較多的時(shí)候,可以第一次使用material,這樣可以動(dòng)態(tài)的生成一個(gè)material實(shí)例,然后再使用sharedmaterial,動(dòng)態(tài)的修改這個(gè)新生成的material,而且不會(huì)創(chuàng)建新的material。

https://blog.uwa4d.com/archives/optimzation_memory_2.html

一般情況下,資源屬性的改變情況都是固定的,并非隨機(jī)出現(xiàn)。比如,假設(shè)GameObject受到攻擊時(shí),其Material屬性改變隨攻擊類型的不同而有三種不同的參數(shù)設(shè)置。那么,對(duì)于這種需求,我們建議你直接制作三種不同的Material,在Runtime情況下通過(guò)代碼直接替換對(duì)應(yīng)GameObject的Material,而非改變其Material的屬性。這樣,你會(huì)發(fā)現(xiàn),成百上千的instance Material在內(nèi)存中消失了,取而代之的,則是這三個(gè)不同的Material資源。

上述內(nèi)容就是Unity3D Mesh中material和sharedMaterial的區(qū)別及內(nèi)部實(shí)現(xiàn)的推斷是怎樣的,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

本文標(biāo)題:Unity3DMesh中material和sharedMaterial的區(qū)別及內(nèi)部實(shí)現(xiàn)的推斷是怎樣的
標(biāo)題網(wǎng)址:http://bm7419.com/article26/igogjg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)、網(wǎng)站改版網(wǎng)站導(dǎo)航、微信公眾號(hào)、網(wǎng)站營(yíng)銷網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

綿陽(yáng)服務(wù)器托管