手遊項目做碰撞的時候,有關一切物理的東西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