项目中的预制件或者模型文件,去除不必要的依赖Default-Material。

一、什么是Default-Material

Default-Material是Unity内置的材质,并且依赖Standard Shader。

如果一个物体依赖了这个材质,在场景中是会显示成紫色方块,并且在打包的时候编译shader非常耗时,并且会造成大量的冗余。

所有这完全是一个没要必要引用的东西,可以使用工具检查项目,并且达到一键去除的功能。

二、查找项目中的Default-Material

在这里首先要感谢Unity 查找unity内置资源的工具这篇博文博主提供的查找代码。

引用到项目后,做了进一步的精简,需要的是查找引用了Default-Material的资源。

整体思路:

0.使用编辑器常用接口,去查找文件,并且列举出来。常用接口可以查看我的这边文章Unity总结整理编辑器常用接口

1.搜索项目资源目录中的.prefab和.fbx文件,预制件和模型文件

2.判断文件上的Renderer是否有引用了Default-Material的材质,用名字匹配即可

3.按照预制件、模型文件,分别用不同的方式去除文件。

三、去除预制件上的Default-Material

找到预制件上的renderer,检查是否引用了Default-Material,重新赋值一个空的材质,然后保存这个资源。

这里需要注意的是不能直接render.sharedMaterials = null,或者mats [i] = null。

void RemoveDefaultMaterial(string path)
{
    GameObject obj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
    Renderer[] renders = obj.GetComponentsInChildren<Renderer>();
    if (renders == null) return;
    string materialName = "Default-Material";
    foreach (var render in renders)
    {
        Material[] mats = render.sharedMaterials;
        for (int i = 0; i < mats.Length; i++)
        {
            if (null != mats[i] && mats[i].name == materialName)
            {
                render.sharedMaterials = new Material[render.sharedMaterials.Length];
            }
        }
    }
    AssetDatabase.SaveAssets();
    AssetDatabase.Refresh();
}

四、去除模型上的Default-Material

把模型的Import Material去掉勾选,然后再去除Default-Material。

与美术约定,模型只需要网格即可,导入模型做成预制件,然后在预制件中依赖对应的shader即可。

用工具检查到有问题的模型后,使用AssetDatabase.ImportAsset重新导入这个资源,然后在导入处理代码中统一处理。

这样在下次导入其他模型时,也会使用去除代码。

注意:importMaterials=false这个会修改meta文件,受版本控制。而render.sharedMaterials = new Material[render.sharedMaterials.Length]不受版本控制,所以如果检查到有问题,需要在打包机上执行。

public class RemoveDefaultMaterial : AssetPostprocessor
{
    void OnPreprocessModel()
    {
        ModelImporter modelImporter = assetImporter as ModelImporter;
        modelImporter.importMaterials = false;
    }

    void OnPostprocessModel(GameObject model)
    {
        Renderer[] renders = model.GetComponentsInChildren<Renderer>();
        if (renders == null) return;
        foreach (Renderer render in renders)
        {
            render.sharedMaterials = new Material[render.sharedMaterials.Length];
        }
    }
}