Unity填坑笔记(一)—Default-Material

0. 写在之前

本来创业之后,博客都计划整理成分量比较足、沉淀比较够的内容来做,但在游戏开发过程中,也不断踩了Unity的很多小坑。它们不足以整理成条理清晰、内容丰富的博客文章,但是填坑过程又花费了半天到一天的时间,如果记录下来给猜到同样坑的同学,也许就可以省去那么一些时间,于是决定新开一个小的笔记系列——Unity填坑笔记,我简单记录,您快速查看。

1. 起因

目前在做大世界的动态加载,加载的时候有明显的顿卡,于是通过Profile来查顿卡的原因,发现有Shader.Parse的调用,占用时间非常高,中低配机器上大约200ms+。
于是做了Shader的预编译,提前WarmUp用到的Shader,再次打包测试,依然有Shader.Parse的调用,通过Sample内存的差异来看编译了哪些Shader,其中有一大部分是Standard。

内存中有Standard的Shader

2. 原因

通过Profile右侧的Referenced By,可以查看当前的Asset被哪个东西引用,看了一下发现,都是被FBX引用了,导入的FBX文件中,都使用了Default-Material,而这个Default-Material是使用的Standard Shader。

FBX使用的Default-Material

3. 解决方法

这个Default-Material并不能被修改,于是我搜索了半天,找到一个插件号称可以支持替换Default-Material,够买来看了下,用的是在AssetPostprocessor中OnAssignMaterialModel来替换材质的方法,实例代码供参考:

    protected virtual Material OnAssignMaterialModel(Material previousMaterial, Renderer renderer)
    {
        var materialPath = "Assets/Default_Materiall.mat";

        if (AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material)))
        {
            return AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material)) as Material;
        }

        Debug.Log(previousMaterial.name);

        return previousMaterial;
    }

这样只需要提供一个自定义的Default_Material.mat文件,重新导入所有的FBX文件,就可以进行替换了。
另外一个种方法是UWA群里的朋友提供了,就是删除掉Defualt-Material,沿着这个思路搜索了一下,发现网上已经有解决方案:删除FBX的默认材质
示例代码如下:

    /// <summary>
    /// 对于模型,删除共享材质,保证不会将包括Standard这样的材质打包到游戏中。
    /// </summary>
    /// <param name="model"></param>
    public void OnPostprocessModel(GameObject model)
    {
        Renderer[] renders = model.GetComponentsInChildren<Renderer>();
        if (null != renders)
        {
            foreach (Renderer render in renders)
            {
                render.sharedMaterials = new Material[render.sharedMaterials.Length];
            }
        }
    }

注意这里不能将sharedMaterials设置为null,而是要new一个空的列表给它。
给一个遍历代码来处理所有的FBX文件:

    // 添加重新导入fbx的功能。
    [MenuItem("Assets/Reimport all FBX")]
    public static void ReimportAllFBX()
    {
        var files = AssetDatabase.GetAllAssetPaths();
        foreach (var vv in files)
        {
            var vvLower = vv.ToLower();
            if (vvLower.EndsWith("fbx"))
            {
                AssetDatabase.ImportAsset(vv, ImportAssetOptions.ImportRecursive | ImportAssetOptions.ForceUpdate);
            }
        }
    }

4. 坑

除了前面提到的Default-Material会导致按照AB打包可能重复加载Standard Shader,Unity 5.5.1f版本还有一个坑就是如果用了Remote的Cache Server,会导致AssetDatabase.ImportAsset不会更新内容,因为这个问题坑了我很久。。。因为右键直接ReImport是可以更新的,但是如果想Reimport All,会重新导入贴图,时间占用非常多,因此一直想只处理fbx文件,但是在Unity 5.5.1f版本中一直不太对,后来查到这个bug Report
可恨的是,我本地貌似调用前面写的ReimportAllFBX方法会把Cache Server设置为Remote!虽然不能理解,但是现象貌似就是如此。。。
最后,升级了Unity版本到5.5.3f,依然关闭Cache Server,重新导入所有的,可以了。
tips:可以通过Project中只显示model来过滤查看所有的模型是否都是粉色的来保证所有的Default-Material都被干掉了。

验证所有model都变粉了~

推荐阅读更多精彩内容