美术创建材质的时候如果没有选择shader,那么创建的是默认shader材质,文本编辑器打开材质文件(.mat),会发现有很多没有默认的texture,如下图,此时美术切换材质到目标shader,虽然编辑器里面的inspector会变化,但是查看材质文件(.mat),发现那些贴图的定义还是在,这种情况下会被uwa检测为 “包含空纹理采样的材质”。如果在创建材质时选中shader,则没有这个问题。
因为美术创建材质之后要不停切换shader测试效果,所以写了一个工具,在美术调完效果后,操作材质,生成一份该shader的材质,并把属性赋值过去,以此删除掉空引用。
!!!注:该问题不清楚unity打包时是否会自动清除,因为没法检测。但是unity切换shader,导致贴图引用冗余依赖的问题,经测试在打包时会自动去除掉无效依赖,所以如果没有需要使用编辑器依赖的情况下,是不需要再写脚本处理冗余依赖的。
以下为材质优化脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
public class MaterialOptimize : Editor
{
[MenuItem("Assets/MaterialOptimize(重新导出当前shader及属性的材质)", false)]
static void MaterialOptimizeMethod()
{
var objs = Selection.objects;
foreach (var obj in objs)
{
var sourcePath = AssetDatabase.GetAssetPath(obj);
Material sourceMaterial = obj as Material;
Material newMaterial = new Material(sourceMaterial.shader);//创建shader对应的材质
var s = sourceMaterial.shader;
int length = s.GetPropertyCount();//获取shader的属性
Debug.LogError(length);
for (int i = 0; i < length; i++)
{
Debug.LogError($"{i} => {s.GetPropertyName(i)} => {s.GetPropertyType(i)}");
string pName = s.GetPropertyName(i);//获取对应的属性名
ShaderPropertyType pType = s.GetPropertyType(i);//获取对应的属性类型
//根据不同的类型对材质进行赋值
switch (pType)
{
case ShaderPropertyType.Color:
newMaterial.SetColor(pName, sourceMaterial.GetColor(pName));
break;
case ShaderPropertyType.Vector:
newMaterial.SetVector(pName, sourceMaterial.GetVector(pName));
break;
case ShaderPropertyType.Float:
newMaterial.SetFloat(pName, sourceMaterial.GetFloat(pName));
break;
case ShaderPropertyType.Range:
newMaterial.SetFloat(pName, sourceMaterial.GetFloat(pName));
break;
case ShaderPropertyType.Texture:
newMaterial.SetTexture(pName, sourceMaterial.GetTexture(pName));
break;
default:
break;
}
}
//保存,替换
AssetDatabase.CreateAsset(newMaterial, sourcePath /*$"Assets/3DCharacter/Test/{obj.name}.mat"*/);
}
AssetDatabase.Refresh();
}
[MenuItem("Assets/MaterialOptimize", true)]
static bool MaterialOptimizeMethodEnable()
{
return Selection.activeObject is Material;
}
}