Unity開發優化----刪除多餘的MeshCollider和Animation組件

     手遊項目做碰撞的時候,有關一切物理的東西Unity對手機支持的並不好,多餘的MeshCollider 和Animation 空的組件,這倆東西很佔效率的。比如下圖這樣的組件。


      還有場景的材質最好用Mobile/Diffuse,它會比Diffuse的shader效率高很多,因爲它會減少每個點的一次乘法。但是有時候美術需要做貼圖的變色, 那就不能用Mobile/Diffuse了。但是後來我看了一下有很多材質用的是Diffuse,但是顏色那裏是純白色,那麼shader在渲染的時候每個點都多餘的進行了一次乘法的運算(效率白白的浪費了)。。。

     作爲程序我們首先要避免策劃和美術犯錯,果斷的寫一個插件吧,美術在上傳場景之前先運行一下插件,把沒用的組件刪除掉。

[MenuItem("Tools/刪除場景沒用的MeshCollider和Animation")]
	static public void Remove()
	{
	  //獲取當前場景裏的所有遊戲對象
		GameObject []rootObjects = (GameObject[])UnityEngine.Object.FindObjectsOfType(typeof(GameObject));
		//遍歷遊戲對象
		foreach(GameObject go in rootObjects)
		{
		  //如果發現Render的shader是Diffuse並且顏色是白色,那麼將它的shader修改成Mobile/Diffuse
			if(go != null && go.transform.parent != null)
			{
					Renderer render = go.GetComponent<Renderer>();
				  if( render != null &&render.sharedMaterial != null && render.sharedMaterial.shader.name == "Diffuse" && render.sharedMaterial.color == Color.white)
					{
					  render.sharedMaterial.shader = Shader.Find("Mobile/Diffuse");
					}
			}
 
      //刪除所有的MeshCollider
			foreach(MeshCollider collider in UnityEngine.Object.FindObjectsOfType(typeof(MeshCollider)))
			{
				DestroyImmediate(collider);
			}
 
			//刪除沒有用的動畫組件
			foreach(Animation animation in UnityEngine.Object.FindObjectsOfType(typeof(Animation)))
			{
				if(animation.clip == null)
					DestroyImmediate(animation);
			}
			foreach(Animator animator in UnityEngine.Object.FindObjectsOfType(typeof(Animator)))
			{
                                 if(animator.clip==null){
				<span style="white-space:pre">	</span>DestroyImmediate(animator);
                               }
			}
		}
		//保存
		AssetDatabase.SaveAssets();
	}

如果你的項目中美術已經上傳了很多場景,並且你也不知道那個場景有問題,那就快寫一個批量刪除所有場景的插件吧。

結合上面的代碼

	[MenuItem("Tools/批量刪除所有場景中的MeshCollider 和Animation")]
	static public void RemoveAll()
	{
		//遍歷所有場景
		foreach (UnityEditor.EditorBuildSettingsScene scene in UnityEditor.EditorBuildSettings.scenes)
		{
		  //當場景啓動中
			if (scene.enabled)
			{
			 //打開這個場景
				EditorApplication.OpenScene(scene.path);
				//刪除該場景中的所有MeshCollider 和Animation
				Remove();
			}
		}
		//保存
		EditorApplication.SaveScene();
	}

另外清注意 只有你的場景在BuildSettings頁面中註冊過UnityEditor.EditorBuildSettings.scenes才能獲取場景。如果你的場景沒有加到BuildSetting中。可以使用以下代碼:

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
public class Easy : Editor {
 
	[MenuItem("Tools/同步所有場景到SceneSetting文件")]
	static void CheckSceneSetting()
	{
		List<string> dirs = new List<string>();
		GetDirs(Application.dataPath,ref dirs);
		EditorBuildSettingsScene[] newSettings = new EditorBuildSettingsScene[dirs.Count];
		for(int i =0; i< newSettings.Length;i++)
		{
			newSettings[i] = new EditorBuildSettingsScene(dirs[i],true);
		}
		EditorBuildSettings.scenes = newSettings;
		EditorApplication.SaveAssets();
	}
	private static void GetDirs(string dirPath, ref List<string> dirs)
	{
		foreach (string path in Directory.GetFiles(dirPath))
		{
			if(System.IO.Path.GetExtension(path) == ".unity") 
			{
				dirs.Add(path.Substring(path.IndexOf("Assets/")));
			}
		}
		if (Directory.GetDirectories(dirPath).Length > 0)
		{
			foreach (string path in Directory.GetDirectories(dirPath))
				GetDirs(path,ref dirs);
		}
	}
}
合併drallCall 最簡單的辦法就是讓美術上傳模型的時候勾選一下Static,這樣Unity會自動幫我們合併DrawCall.我建議你還是不要相信美術了。幫他們做工具吧。。

或者你也可以在遊戲運行中動態的添加,找一個合適的位置寫入如下代碼。他會把該遊戲對象以及所有子對象全部合併DrawCall。

StaticBatchingUtility.Combine(gameObject);

這樣合併DrawCall的很方便,而且也很簡單。但是無法修改所有子對象的座標、旋轉、縮放了,但是可以修改父對象。如下圖所示,比如我給a 設置了static屬性,或者 Combine(a.gameObject) ,那麼如果代碼中你需要操作b 或者 c 的Transform那麼是不行的, 但是你可以操作a。 他會帶着 b 和c 一起Transform。



【轉載自】雨鬆MOMO 2014年05月04日 於 雨鬆MOMO程序研究院 

發表本文固定鏈接: http://www.xuanyusong.com/archives/2564


發佈了16 篇原創文章 · 獲贊 16 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章