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);
}
}
}