using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using System;
|
|
// using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
|
|
/// <summary>
|
|
/// 给选中的特效添加脚本的
|
|
/// </summary>
|
|
namespace ParticleEffectProfilerNameSpace {
|
|
[InitializeOnLoad]
|
|
public class BatchTestParticleEffect
|
|
{
|
|
/// <summary>
|
|
/// 需要有一个摄像机
|
|
/// 每隔5s检查一个特效
|
|
/// 检查结果保存在 \code\u3d\Assets\StreamingAssets\profiler_log\
|
|
/// </summary>
|
|
|
|
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<Camera>();
|
|
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<int, SaveWaitQueueCsvData> csvDataDic2 = SaveWaitQueueCsvData.LoadCsvData<SaveWaitQueueCsvData>(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<ParticleEffectScript>(true);
|
|
if (particleEffectScript.Length == 0)
|
|
{
|
|
particle_prefab.AddComponent<ParticleEffectScript>();
|
|
}
|
|
// 取消标记
|
|
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);
|
|
}
|
|
}
|
|
}
|