Unity研究院之多余的MeshCollider和Animation组件

http://www.xuanyusong.com/archives/2564


        如果你是在做手游项目,我强烈建立不要做碰撞,有关一切物理的东西Unity对手机支持的并不好,如果不信你可以试试效率你就知道。美术兄弟,每次给过来的场景,都会带上MeshCollider 和Animation 空的组件。这俩东西很占效率的,不信你可以用Profiler 看看。如果你让美工们上传场景的时候手动检查一下,把MeshCollider和Animation空的组件都删掉,我可以很负责的告诉你,他们肯定会忘删除或者错删。。。比如下图这样的组件。

屏幕快照 2014-05-04 下午9.11.54

          还有场景的材质最好用Mobile/Diffuse,他会比Diffuse的shader效率高很多,因为它会减少每个点的一次乘法。但是有时候美术需要做贴图的变色, 那就不能用Mobile/Diffuse了。但是后来我看了一下有很多材质用的是Diffuse,但是颜色那里是纯白色,那么shader在渲染的时候每个点都多余的进行了一次乘法的运算(效率白白的浪费了)。。。

           作为程序我们首先要避免策划和美术犯错,果断的写一个插件吧,美术在上传场景之前让运行一下插件,把没用的组件删除掉。

01 [MenuItem("Tools/删除场景没用的MeshCollider和Animation")]
02 static public void Remove()
03 {
04   //获取当前场景里的所有游戏对象
05     GameObject []rootObjects = (GameObject[])UnityEngine.Object.FindObjectsOfType(typeof(GameObject));
06     //遍历游戏对象
07     foreach(GameObject go in rootObjects)
08     {
09       //如果发现Render的shader是Diffuse并且颜色是白色,那么将它的shader修改成Mobile/Diffuse
10         if(go != null && go.transform.parent != null)
11         {
12                 Renderer render = go.GetComponent<Renderer>();
13               if( render != null &&render.sharedMaterial != null && render.sharedMaterial.shader.name == "Diffuse" && render.sharedMaterial.color == Color.white)
14                 {
15                   render.sharedMaterial.shader = Shader.Find("Mobile/Diffuse");
16                 }
17         }
18  
19   //删除所有的MeshCollider
20         foreach(MeshCollider collider in UnityEngine.Object.FindObjectsOfType(typeof(MeshCollider)))
21         {
22             DestroyImmediate(collider);
23         }
24  
25         //删除没有用的动画组件
26         foreach(Animation animation in UnityEngine.Object.FindObjectsOfType(typeof(Animation)))
27         {
28             if(animation.clip == null)
29                 DestroyImmediate(animation);
30         }
31  
32   //应该没有人用Animator吧? 避免美术弄错我都全部删除了。
33         foreach(Animator animator in UnityEngine.Object.FindObjectsOfType(typeof(Animator)))
34         {
35                 DestroyImmediate(animator);
36         }
37     }
38     //保存
39     AssetDatabase.SaveAssets();
40 }

 如果你的项目中美术已经上传了很多场景,并且你也不知道那个场景有问题,那就快写一个批量删除所有场景的插件吧。

结合上面的代码

 

01 [MenuItem("Tools/批量删除所有场景中的MeshCollider 和Animation")]
02 static public void RemoveAll()
03 {
04     //遍历所有场景
05     foreach (UnityEditor.EditorBuildSettingsScene scene in UnityEditor.EditorBuildSettings.scenes)
06     {
07       //当场景启动中
08         if (scene.enabled)
09         {
10          //打开这个场景
11             EditorApplication.OpenScene(scene.path);
12             //删除该场景中的所有MeshCollider 和Animation
13             Remove();
14         }
15     }
16     //保存
17     EditorApplication.SaveScene();
18 }

 

另外清注意 只有你的场景在BuildSettings页面中注册过UnityEditor.EditorBuildSettings.scenes才能获取场景。如果你的场景没有加到BuildSetting中。 如果想批量添加你可以参考我之前写的文章我还是copy过来吧。

01 using UnityEngine;
02 using System.Collections;
03 using UnityEditor;
04 using System.Collections.Generic;
05 using System.IO;
06 public class Easy : Editor {
07  
08     [MenuItem("Tools/同步所有场景到SceneSetting文件")]
09     static void CheckSceneSetting()
10     {
11         List<string> dirs = new List<string>();
12         GetDirs(Application.dataPath,ref dirs);
13         EditorBuildSettingsScene[] newSettings = new EditorBuildSettingsScene[dirs.Count];
14         for(int i =0; i< newSettings.Length;i++)
15         {
16             newSettings[i] = new EditorBuildSettingsScene(dirs[i],true);
17         }
18         EditorBuildSettings.scenes = newSettings;
19         EditorApplication.SaveAssets();
20     }
21     private static void GetDirs(string dirPath, ref List<string> dirs)
22     {
23         foreach (string path in Directory.GetFiles(dirPath))
24         {
25             if(System.IO.Path.GetExtension(path) == ".unity")
26             {
27                 dirs.Add(path.Substring(path.IndexOf("Assets/")));
28             }
29         }
30         if (Directory.GetDirectories(dirPath).Length > 0)
31         {
32             foreach (string path in Directory.GetDirectories(dirPath))
33                 GetDirs(path,ref dirs);
34         }
35     }
36 }

        合并drallCall 最简单的办法就是让美术上传模型的时候勾选一下Static,这样Unity会自动帮我们合并DrawCall.我建议你还是不要相信美术了。帮他们做工具吧。。

 屏幕快照 2014-05-04 下午9.30.41

 

       或者你也可以在游戏运行中动态的添加,找一个合适的位置写入如下代码。他会把该游戏对象以及所有子对象全部合并DrawCall。

 

1 StaticBatchingUtility.Combine(gameObject);

 

         这样合并DrawCall的很方便,而且也很简单。但是无法修改所有子对象的坐标、旋转、缩放了,但是可以修改父对象。如下图所示,比如我给a 设置了static属性,或者 Combine(a.gameObject) ,那么如果代码中你需要操作b 或者 c 的Transform那么是不行的, 但是你可以操作a。 他会带着 b 和c 一起Transform。

屏幕快照 2014-05-04 下午9.36.32

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值