using UnityEditor; using UnityEngine; using UnityEngine.UI; using System; // using System.Collections; using System.Collections.Generic; using System.IO; /// /// 给选中的特效添加脚本的 /// namespace ParticleEffectProfilerNameSpace { [InitializeOnLoad] public class BatchTestParticleEffect { /// /// 需要有一个摄像机 /// 每隔5s检查一个特效 /// 检查结果保存在 \code\u3d\Assets\StreamingAssets\profiler_log\ /// static string outPutTitleStr = "特效名,贴图内存(KB) 建议:<1024KB,贴图数量 建议:<5,粒子组件数 建议:<10,粒子数量 建议:<50,DrawCall 建议:<10,以下选项会导致特效无法自动剔除:";//检查结果分类名 //////////////////分割线///////////////////分割线//////////////////分割线//////////////分割线//////////////////// static string tempOutPutStr = "";//临时单条检查结果 static bool isRestart = false; private const string RequestTestKey = "BatchTestParticleEffectRquestTest";// 打标记,指定是特效检查中 private const string EffectStatusKey = "BatchTestParticleEffectStatusInt";// 检查进程状态 private const string EffectWaitAddKey = "BatchTestParticleEffectWaitAddKey";// 打标记,指定是待增加新节点 private const string EffectIndexKey = "BatchTestParticleEffectIndexInt";// 检查进程的进度index private const string EffectLastTimeKey = "BatchTestParticleEffectLastTimeFloat";// 检查进程的控制时间 private const string ResultOutPutKey = "BatchTestParticleEffectResultOutPutKey";// 检查结果总数据 private const string CheckAllNumKey = "BatchTestParticleCheckAllNumKey";// 检查总长度 private const string CurFileIdKey = "BatchTestParticleCurFileIdKey";// 当前检查的文件名 private const string CameraNameKey = "BatchTestParticleCameraNameKey";// 检查所用的摄像机名字 [MenuItem("Assets/特效批量检查", false)] private static void BatchCheckStart() { //保存摄像机名 bool find_camera = SaveCameraName(); if (!find_camera){ EditorUtility.DisplayDialog("Error", "当前根节点没有可用摄像机节点", "Ok"); return; } // 检查文件目录是否存在 string folder_path = Application.streamingAssetsPath + @"\profiler_log"; if (!Directory.Exists(folder_path)) Directory.CreateDirectory(folder_path); // 获得整个选中列表,用来备用 UnityEngine.Object[] batch_check_list = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.TopLevel); //检查对象是否正确start foreach (UnityEngine.Object obj in batch_check_list) { string res_path = AssetDatabase.GetAssetPath(obj); GameObject layout_prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(res_path, typeof(UnityEngine.Object)) as GameObject; if (layout_prefab == null) { EditorUtility.DisplayDialog("Error", "检查对象错误,请检查:" + res_path, "Ok"); return; } } //检查对象是否正确end EditorPrefs.SetInt(CheckAllNumKey, batch_check_list.Length); if (batch_check_list.Length > 0) { EditorPrefs.SetString(CurFileIdKey, System.DateTime.Now.ToFileTime().ToString());//保存文件名id WriteDirCsvWait();//保存当前选中列表待使用 //已经在播放状态,关闭 if (EditorApplication.isPlaying) { EditorApplication.isPlaying = false; } // 初始化数据 EditorPrefs.SetString(ResultOutPutKey, outPutTitleStr);//批处理状态-》开始 EditorPrefs.SetBool(RequestTestKey, true); EditorPrefs.SetString(EffectStatusKey, "Going");//批处理状态-》开始 EditorPrefs.SetFloat(EffectLastTimeKey, Time.time); int index = 1;//从第一个开始 EditorPrefs.SetInt(EffectIndexKey, index); EditorPrefs.SetString(EffectWaitAddKey, "Non");//设置初始 AddOneNode( index ); BatchCheckOne(index); } else { EditorApplication.isPlaying = false; } } //设置摄像机名字 private static bool SaveCameraName( ){ foreach (GameObject rootObj in UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects()) { Camera renders = rootObj.GetComponent(); if (renders != null) { EditorPrefs.SetString(CameraNameKey, rootObj.name); return true; } } return false; } /// 读取路径表CSV数据 private static string GetCacheDirCsvWait( int index ){ string filePath = Application.streamingAssetsPath + "/profiler_log/NameList" + EditorPrefs.GetString(CurFileIdKey) + ".csv"; Dictionary csvDataDic2 = SaveWaitQueueCsvData.LoadCsvData(filePath); if ((csvDataDic2.Count) >= index){ SaveWaitQueueCsvData csvDemo2 = csvDataDic2[index]; return csvDemo2.Name; } else{ return ""; } } /// 写入路径表CSV数据 private static void WriteDirCsvWait(){ /* 把CSV文件按行存放,每一行的ID作为key值,内容作为value值 */ UnityEngine.Object[] batch_check_list = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.TopLevel); string temp_str = "ID,Name"; for (int i = 0; i < batch_check_list.Length; i++) { temp_str = temp_str + ";"; temp_str = temp_str + (i+1) + "," + AssetDatabase.GetAssetPath(batch_check_list[i]); } string filePath = Application.streamingAssetsPath + "/profiler_log/NameList" + EditorPrefs.GetString(CurFileIdKey) + ".csv"; string[] strs = temp_str.Split(';'); CSVOptionTool.WriteCsv(strs, filePath); } /// 工作结束删除路径表CSV文件 private static void RemoveFileDirCsvWait(){ string filePath = Application.streamingAssetsPath + "/profiler_log/NameList" + EditorPrefs.GetString(CurFileIdKey) + ".csv"; File.Delete(filePath); File.Delete(filePath + ".mata"); } static BatchTestParticleEffect() { EditorApplication.update += Update; EditorApplication.playmodeStateChanged += PlaymodeStateChanged; } public static void BatchCheckOne(int checkIndex ) { string result_str = GetCacheDirCsvWait(checkIndex); if (result_str != "") { if (checkIndex != 1){ //要在停止前保存,不然会丢数据 WriteNewOutPutData(); } // 停止运行 if (EditorApplication.isPlaying) { EditorApplication.isPlaying = false; } if (checkIndex != 1){ EditorPrefs.SetString(EffectWaitAddKey, "WaitAdd"); } else{ // 运行 EditorPrefs.SetString(EffectWaitAddKey, "Non"); ApplicationPlaying(); } } else { OverCheckCall(false); } } // 加入一个特效节点 public static void AddOneNode(int addIndex ) { if (EditorApplication.isPlaying) { EditorApplication.isPlaying = false; } GameObject main_camera = GameObject.Find(EditorPrefs.GetString(CameraNameKey)); // 清除节点下的子节点 for (int i = main_camera.transform.childCount - 1; i >= 0; i--) { GameObject.DestroyImmediate(main_camera.transform.GetChild(i).gameObject); } // 创建测试节点 string result_str = GetCacheDirCsvWait(addIndex); if (result_str != "") { GameObject layout_prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(result_str, typeof(UnityEngine.Object)) as GameObject; if (layout_prefab == null) { OverCheckCall(true); EditorUtility.DisplayDialog("Error", "检查对象错误,请检查:" + result_str, "Ok"); return; } GameObject particle_prefab = GameObject.Instantiate(layout_prefab) as GameObject; particle_prefab.transform.parent = main_camera.transform; particle_prefab.transform.localPosition = new Vector3(0, 0, 10); particle_prefab.transform.localScale = Vector3.one; Selection.activeGameObject = particle_prefab; // 加脚本 var particleEffectScript = particle_prefab.GetComponentsInChildren(true); if (particleEffectScript.Length == 0) { particle_prefab.AddComponent(); } // 取消标记 EditorPrefs.SetString(EffectWaitAddKey, "AddOver"); } else { OverCheckCall(false); } } //特效批量检查结束 private static void OverCheckCall(bool mask_write) { if (!mask_write) { WriteNewOutPutData(); } EditorApplication.isPlaying = false; EditorPrefs.SetString(EffectStatusKey, "WaitOver");//批处理状态-》等待关闭 EditorUtility.ClearProgressBar(); RemoveFileDirCsvWait(); EditorUtility.DisplayDialog("提示", "特效批量检查结束,结果文件ID为:" + EditorPrefs.GetString(CurFileIdKey) , "Ok"); OpenDirectory( Application.streamingAssetsPath + "/profiler_log" ); } private static void Update() { int checkIndex = EditorPrefs.GetInt(EffectIndexKey); int all_len = EditorPrefs.GetInt(CheckAllNumKey); string wait_add_status = EditorPrefs.GetString(EffectWaitAddKey);//布尔值等待增节点 if ( EditorPrefs.HasKey(RequestTestKey) && EditorApplication.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode) { bool isCancel = EditorUtility.DisplayCancelableProgressBar(string.Format("特效检查资源中({0}/{1})", checkIndex, all_len), "", (float)checkIndex / (float)all_len); if (isCancel) { OverCheckCall(true); return; } if (EditorPrefs.GetString(EffectStatusKey) == "Going"){//批处理状态-》开始 // 计时器,每隔5s检查一个特效 float lastTime = EditorPrefs.GetFloat(EffectLastTimeKey); float curTime = Time.time; if (curTime - lastTime >= 5) { EditorPrefs.SetFloat(EffectLastTimeKey, curTime); EditorPrefs.SetInt(EffectIndexKey, checkIndex+1); BatchCheckOne(checkIndex+1); }else if ((curTime - lastTime) < 0) { //矫正时间 EditorPrefs.SetFloat(EffectLastTimeKey, curTime); } } } if ( EditorPrefs.HasKey(RequestTestKey) && !EditorApplication.isPlaying) { if (wait_add_status == "WaitAdd"){ AddOneNode(checkIndex ); }else if (wait_add_status == "AddOver") { ApplicationPlaying(); } } } //运行状态切换的回调 private static void PlaymodeStateChanged() { if (isRestart) { // 要重启游戏的情况 EditorApplication.isPlaying = true; isRestart = false; } if (!EditorApplication.isPlaying && EditorPrefs.GetString(EffectStatusKey) == "WaitOver"){ EditorPrefs.SetString(EffectStatusKey, "Non");//批处理状态-》结束 EditorPrefs.DeleteKey(RequestTestKey); // 清除节点下的子节点 GameObject main_camera = GameObject.Find(EditorPrefs.GetString(CameraNameKey)); for (int i = main_camera.transform.childCount - 1; i >= 0; i--) { GameObject.DestroyImmediate(main_camera.transform.GetChild(i).gameObject); } } } //运行游戏 public static void ApplicationPlaying() { if (EditorApplication.isPlaying) { //已经在播放状态,使其重新开始 EditorApplication.isPlaying = false; isRestart = true; } else{ EditorApplication.isPlaying = true; } } // 保存临时输出数据 public static void SaveTempOutPutData(string outPut){ tempOutPutStr = outPut; } //写入新数据 public static void WriteNewOutPutData(){ string outPutString = EditorPrefs.GetString(ResultOutPutKey); outPutString = outPutString + ";" + tempOutPutStr; EditorPrefs.SetString(ResultOutPutKey, outPutString); string filePath = Application.streamingAssetsPath + "/profiler_log/OutPut" + EditorPrefs.GetString(CurFileIdKey) + ".csv"; string[] strs = outPutString.Split(';'); CSVOptionTool.WriteCsv(strs, filePath); } //打开文件夹 public static void OpenDirectory(string path){ if (string.IsNullOrEmpty(path)) return; path=path.Replace("/", "\\"); if (!Directory.Exists(path)){ Debug.LogError("No Directory: " + path); return; } System.Diagnostics.Process.Start("explorer.exe", path); } } }