http://www.xuanyusong.com/archives/2564
如果你是在做手游项目,我强烈建立不要做碰撞,有关一切物理的东西Unity对手机支持的并不好,如果不信你可以试试效率你就知道。美术兄弟,每次给过来的场景,都会带上MeshCollider 和Animation 空的组件。这俩东西很占效率的,不信你可以用Profiler 看看。如果你让美工们上传场景的时候手动检查一下,把MeshCollider和Animation空的组件都删掉,我可以很负责的告诉你,他们肯定会忘删除或者错删。。。比如下图这样的组件。
还有场景的材质最好用Mobile/Diffuse,他会比Diffuse的shader效率高很多,因为它会减少每个点的一次乘法。但是有时候美术需要做贴图的变色, 那就不能用Mobile/Diffuse了。但是后来我看了一下有很多材质用的是Diffuse,但是颜色那里是纯白色,那么shader在渲染的时候每个点都多余的进行了一次乘法的运算(效率白白的浪费了)。。。
作为程序我们首先要避免策划和美术犯错,果断的写一个插件吧,美术在上传场景之前让运行一下插件,把没用的组件删除掉。
01 | [MenuItem( "Tools/删除场景没用的MeshCollider和Animation" )] |
02 | static public void Remove() |
05 | GameObject []rootObjects = (GameObject[])UnityEngine.Object.FindObjectsOfType( typeof (GameObject)); |
07 | foreach (GameObject go in rootObjects) |
10 | if (go != null && go.transform.parent != null ) |
12 | Renderer render = go.GetComponent<Renderer>(); |
13 | if ( render != null &&render.sharedMaterial != null && render.sharedMaterial.shader.name == "Diffuse" && render.sharedMaterial.color == Color.white) |
15 | render.sharedMaterial.shader = Shader.Find( "Mobile/Diffuse" ); |
20 | foreach (MeshCollider collider in UnityEngine.Object.FindObjectsOfType( typeof (MeshCollider))) |
22 | DestroyImmediate(collider); |
26 | foreach (Animation animation in UnityEngine.Object.FindObjectsOfType( typeof (Animation))) |
28 | if (animation.clip == null ) |
29 | DestroyImmediate(animation); |
33 | foreach (Animator animator in UnityEngine.Object.FindObjectsOfType( typeof (Animator))) |
35 | DestroyImmediate(animator); |
39 | AssetDatabase.SaveAssets(); |
如果你的项目中美术已经上传了很多场景,并且你也不知道那个场景有问题,那就快写一个批量删除所有场景的插件吧。
结合上面的代码
01 | [MenuItem( "Tools/批量删除所有场景中的MeshCollider 和Animation" )] |
02 | static public void RemoveAll() |
05 | foreach (UnityEditor.EditorBuildSettingsScene scene in UnityEditor.EditorBuildSettings.scenes) |
11 | EditorApplication.OpenScene(scene.path); |
17 | EditorApplication.SaveScene(); |
另外清注意 只有你的场景在BuildSettings页面中注册过UnityEditor.EditorBuildSettings.scenes才能获取场景。如果你的场景没有加到BuildSetting中。 如果想批量添加你可以参考我之前写的文章我还是copy过来吧。
02 | using System.Collections; |
04 | using System.Collections.Generic; |
06 | public class Easy : Editor { |
08 | [MenuItem( "Tools/同步所有场景到SceneSetting文件" )] |
09 | static void CheckSceneSetting() |
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++) |
16 | newSettings[i] = new EditorBuildSettingsScene(dirs[i], true ); |
18 | EditorBuildSettings.scenes = newSettings; |
19 | EditorApplication.SaveAssets(); |
21 | private static void GetDirs( string dirPath, ref List< string > dirs) |
23 | foreach ( string path in Directory.GetFiles(dirPath)) |
25 | if (System.IO.Path.GetExtension(path) == ".unity" ) |
27 | dirs.Add(path.Substring(path.IndexOf( "Assets/" ))); |
30 | if (Directory.GetDirectories(dirPath).Length > 0) |
32 | foreach ( string path in Directory.GetDirectories(dirPath)) |
33 | GetDirs(path, ref dirs); |
合并drallCall 最简单的办法就是让美术上传模型的时候勾选一下Static,这样Unity会自动帮我们合并DrawCall.我建议你还是不要相信美术了。帮他们做工具吧。。
或者你也可以在游戏运行中动态的添加,找一个合适的位置写入如下代码。他会把该游戏对象以及所有子对象全部合并DrawCall。
1 | StaticBatchingUtility.Combine(gameObject); |
这样合并DrawCall的很方便,而且也很简单。但是无法修改所有子对象的坐标、旋转、缩放了,但是可以修改父对象。如下图所示,比如我给a 设置了static属性,或者 Combine(a.gameObject) ,那么如果代码中你需要操作b 或者 c 的Transform那么是不行的, 但是你可以操作a。 他会带着 b 和c 一起Transform。