美文网首页unity优化Unity3D与游戏开发unity3D技术分享
Unity填坑笔记(一)—Default-Material

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

作者: 董夕 | 来源:发表于2017-06-06 15:51 被阅读567次

    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都变粉了~

    相关文章

      网友评论

      • jonbb:游戏中没有把fbx 拆分?模型和骨骼分别用预制保存,render自己游戏中创建或预制加载,就能不引用fbx材质了。
        董夕:模型我们是使用了prefab的方式,但是prefab中也是引用的fbx文件吧,fbx文件中是有无法修改的对于默认材质的引用的。

      本文标题:Unity填坑笔记(一)—Default-Material

      本文链接:https://www.haomeiwen.com/subject/asogfxtx.html