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;
}
}
}
}
}
文章评论