NGUI的UITexture,可以单独设置渲染材质,但是动态设置材质球参数时候,发现总是不生效,看了下NGUI源码,发现其中的原因
UITexture中的UIDrawCall(对MeshRenderer的封装)并不是直接使用参数mMaterial,而是使用的mDynamicMat,所有的UIWiget设置的都是mMaterial,只有当RebuildMaterial()时才会把之前的mDynamicMat效果并以mMaterial重新new一遍,并拷贝当前mMaterial的所有属性,源码如下:
Material RebuildMaterial () { // Destroy the old material NGUITools.DestroyImmediate(mDynamicMat); // Create a new material CreateMaterial(); mDynamicMat.renderQueue = mRenderQueue; // Update the renderer if (mRenderer != null) { mRenderer.sharedMaterials = new Material[] { mDynamicMat }; mRenderer.sortingLayerName = mSortingLayerName; mRenderer.sortingOrder = mSortingOrder; } return mDynamicMat; }
但真正的问题出在CreateMaterial这个函数中的下面这段代码
if (mMaterial != null) { mDynamicMat = new Material(mMaterial); #if UNITY_EDITOR mDynamicMat.name = "[NGUI] " + mMaterial.name; #else mDynamicMat.name = "[NGUI] "; #endif mDynamicMat.hideFlags = (HideFlags.DontSave | HideFlags.NotEditable); mDynamicMat.CopyPropertiesFromMaterial(mMaterial); #if !UNITY_FLASH string[] keywords = mMaterial.shaderKeywords; for (int i = 0; i < keywords.Length; ++i) mDynamicMat.EnableKeyword(keywords[i]); #endif // If there is a valid shader, assign it to the custom material if (shader != null) { mDynamicMat.shader = shader; } else if (mClipCount != 0) { Debug.LogError(shaderName + " shader doesn't have a clipped shader version for " + mClipCount + " clip regions"); } }
这段代码最后一句 mDynamicMat.shader = shader; 会使先前的mDynamicMat.CopyPropertiesFromMaterial(mMaterial);之后的mDynamicMat参数重新变成默认值
以下是我通过对UITexture扩展的解决方案:
using UnityEngine; using System.Collections.Generic; public partial class UITexture { /// <summary> /// 支持设置UITexture图片同时生效对图片处理的材质 /// </summary> public void SetTextureEx(Texture texture, Material material) { if (mTexture != texture) { if (drawCall != null && drawCall.widgetCount == 1) { if (nullTexture == null) { nullTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false, true); nullTexture.SetPixel(0, 0, Color.clear); nullTexture.Apply(); } mTexture = texture ?? nullTexture; drawCall.mainTexture = texture ?? nullTexture; if (material != null) { mMat = material; if (drawCall.Renderer.material != material) drawCall.Renderer.material = new Material(material); drawCall.Renderer.material.CopyPropertiesFromMaterial(material); } else { this.material = null; } } } } }
文章评论