0. 由来
前段时间策划妹子跑过来提了个需求,说是Unity文件夹下图片太多,有些图片的Texture Type是Sprite(用于UI图集),有些是Default,鱼龙混杂的,单靠眼睛筛选根本管不过来,筛完手动改成Sprite更是人都麻了,于是有了这个工具
1. 批量修改图片格式
1.1 同步版
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;
using System.Text;
public class ChangePicType2Sprite : EditorWindow
{
StringBuilder stringBuilder = new StringBuilder();
static string inputFolder = "";
[MenuItem("PicTools/ChangePicType2Sprite")]
public static void ShowWindow()
{
EditorWindow.GetWindow(typeof(ChangePicType2Sprite));
}
void OnGUI()
{
// 空格
EditorGUILayout.Space(20);
// 样式颜色
GUIStyle style = new GUIStyle();
style.normal.textColor = Color.red;
style.fontSize = 20;
EditorGUILayout.LabelField("注意:该工具只将目录下的png、jpg、jpeg三种图片格式改成Sprite! ", style);
EditorGUILayout.Space(20);
EditorGUILayout.LabelField("注意:图片名称, 文件夹名称不要包含123456(连续数字), 135246这样的可以", style);
EditorGUILayout.Space(20);
EditorGUILayout.LabelField("注意:禁止使用纯数字给图片或文件夹命名!", style);
EditorGUILayout.Space(20);
EditorGUILayout.LabelField("Input Folder : ", inputFolder);
EditorGUILayout.Space(20);
if (GUILayout.Button("Select"))
{
inputFolder = EditorUtility.OpenFolderPanel("Select Input Folder", "", "");
}
EditorGUILayout.Space(20);
if (GUILayout.Button("Change"))
{
ChangeTextures();
}
}
private void OnDestroy()
{
if (inputFolder != "")
{
inputFolder = "";
}
}
void ChangeTextures()
{
string inputPath = inputFolder;
stringBuilder.Clear();
// 获取路径下所有文件路径
GetAllPathFiles(inputPath);
string[] files = stringBuilder.ToString().Split("123456"); // 这里以123456作了分割
Debug.Log(files.Length);
if (files.Length == 0)
{
EditorUtility.DisplayDialog("Failed", "Don't exist png or jpg file in selected filePath...", "OK");
return;
}
foreach (string file in files)
{
string assetPath = GetPathFromAssets(file);
TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (importer != null && importer.textureType != TextureImporterType.Sprite)
{
importer.textureType = TextureImporterType.Sprite;
importer.spriteImportMode = SpriteImportMode.Single;
importer.spritePixelsPerUnit = 100;
importer.filterMode = FilterMode.Bilinear;
importer.textureCompression = TextureImporterCompression.Compressed;
importer.SaveAndReimport();
}
}
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("Success", "Picture type changed successfully.", "OK");
}
// // 递归的获取文件夹、子文件夹下所有图片文件(png、jpg、jpeg)
private void GetAllPathFiles(string inputPath)
{
string[] files1 = Directory.GetFiles(inputPath, "*.png");
string[] files2 = Directory.GetFiles(inputPath, "*.jpg");
string[] files3 = Directory.GetFiles(inputPath, "*.jpeg");
string[] files = files1.Concat(files2).Concat(files3).ToArray();
foreach (var item in files)
{
stringBuilder.Append(item);
stringBuilder.Append("123456");
}
// 获取子文件夹
string[] subFolders = Directory.GetDirectories(inputPath);
foreach (var item in subFolders)
{
GetAllPathFiles(item);
}
}
// 根据文件路径获取特定路径(Assets开头)
private string GetPathFromAssets(string inputPath)
{
int index = 0;
string[] folderStr = inputPath.Split("/");
for (int i = 0; i < folderStr.Length; i++)
{
if (folderStr[i] == "Assets")
{
index = i;
break;
}
}
StringBuilder sb = new StringBuilder();
for (int i = index; i < folderStr.Length; i++)
{
sb.Append(folderStr[i]);
sb.Append("/");
}
// 去除最后一个 / 并返回
return sb.ToString().Substring(0, sb.Length - 1);
}
}
优点:代码好理解,没用异步、Lambda表达式
缺点:卡线程,运行时间长
2.2 异步版
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
public class ChangePicType2Sprite : EditorWindow
{
StringBuilder stringBuilder = new StringBuilder();
static string inputFolder = "";
[MenuItem("PicTools/ChangePicType2Sprite")]
public static void ShowWindow()
{
EditorWindow.GetWindow(typeof(ChangePicType2Sprite));
}
void OnGUI()
{
EditorGUILayout.Space(20);
GUIStyle style = new GUIStyle();
style.normal.textColor = Color.red;
style.fontSize = 20;
EditorGUILayout.LabelField("注意:该工具只将目录下的png、jpg、jpeg三种图片格式改成Sprite! ", style);
EditorGUILayout.Space(20);
EditorGUILayout.LabelField("注意:图片名称, 文件夹名称不要包含123456(连续数字), 135246这样的可以", style);
EditorGUILayout.Space(20);
EditorGUILayout.LabelField("注意:禁止使用纯数字给图片或文件夹命名!", style);
EditorGUILayout.Space(20);
EditorGUILayout.LabelField("Input Folder : ", inputFolder);
EditorGUILayout.Space(20);
if (GUILayout.Button("Select"))
{
inputFolder = EditorUtility.OpenFolderPanel("Select Input Folder", "Assets\\GameResources\\Textures\\UI", "");
}
EditorGUILayout.Space(20);
if (GUILayout.Button("Change"))
{
ChangeTextures();
}
}
private void OnDestroy()
{
if (inputFolder != "")
{
inputFolder = "";
}
}
async void ChangeTextures()
{
await Task.Run(() =>
{
string inputPath = inputFolder;
stringBuilder.Clear();
GetAllPathFiles(inputPath);
string[] files = stringBuilder.ToString().Split("123456");
Debug.Log(files.Length);
if (files.Length == 0)
{
EditorUtility.DisplayDialog("Failed", "Don't exist png or jpg file in selected filePath...", "OK");
return;
}
EditorApplication.delayCall += () =>
{
foreach (string file in files)
{
string assetPath = GetPathFromAssets(file);
TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (importer != null && importer.textureType != TextureImporterType.Sprite)
{
importer.textureType = TextureImporterType.Sprite;
importer.spriteImportMode = SpriteImportMode.Single;
importer.spritePixelsPerUnit = 100;
importer.filterMode = FilterMode.Bilinear;
importer.textureCompression = TextureImporterCompression.Compressed;
importer.SaveAndReimport();
}
}
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("Success", "Picture type changed successfully.", "OK");
};
});
}
private void GetAllPathFiles(string inputPath)
{
string[] files1 = Directory.GetFiles(inputPath, "*.png");
string[] files2 = Directory.GetFiles(inputPath, "*.jpg");
string[] files3 = Directory.GetFiles(inputPath, "*.jpeg");
string[] files = files1.Concat(files2).Concat(files3).ToArray();
foreach (var item in files)
{
stringBuilder.Append(item);
stringBuilder.Append("123456");
}
string[] subFolders = Directory.GetDirectories(inputPath);
foreach (var item in subFolders)
{
GetAllPathFiles(item);
}
}
private string GetPathFromAssets(string inputPath)
{
int index = 0;
string[] folderStr = inputPath.Split("/");
for (int i = 0; i < folderStr.Length; i++)
{
if (folderStr[i] == "Assets")
{
index = i;
break;
}
}
StringBuilder sb = new StringBuilder();
for (int i = index; i < folderStr.Length; i++)
{
sb.Append(folderStr[i]);
sb.Append("/");
}
// 去除最后一个 / 并返回
return sb.ToString().Substring(0, sb.Length - 1);
}
}
优点:不卡线程,运行时间短
缺点:需要掌握Lambda表达式,异步等知识
2. 初始化材质文件参数默认值
我们在项目中可能会有修改材质参数值的需求
例如:
_mat.SetColor(ShaderProperty._part1Color, defaultColor);
由于美术在做模型或资源的时候,自己手动调试查看效果,最后上传了文件或者同一批材质没有初始默认值这一说,但到了程序通过代码操作的时候,可能会造成初始值很乱的现象,所以需要一个工具普照大地,一视同仁
using CoreAvatar.Config;
using CoreAvatar.Mgr;
using System.IO;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
public class ModifyMatFiles : EditorWindow
{
static string folderPath = ResourceConfigLoader.kRootPath + "/Arts/Suits"; // 替换为你指定的文件夹路径
[MenuItem("PicTools/Init Mat Properties")] // 添加自定义菜单项方便执行脚本
private async static void ModifyProperties()
{
await Task.Run(() =>
{
string[] matFiles = Directory.GetFiles(folderPath, "*.mat", SearchOption.AllDirectories);
EditorApplication.delayCall += () =>
{
foreach (string matFile in matFiles)
{
Material _mat = AssetDatabase.LoadAssetAtPath(matFile, typeof(Material)) as Material;
if (_mat != null)
{
if (_mat.HasProperty(ShaderProperty._part1Color))
{
_mat.SetColor(ShaderProperty._part1Color, Color.black);
}
// 可能还有很多参数, 这里不举例了
// ...
// ...
// ...
// ...
EditorUtility.SetDirty(_mat); // 标记资源为"脏",以便保存修改
}
}
AssetDatabase.SaveAssets(); // 保存修改的资源
AssetDatabase.Refresh(); // 刷新资源面板
EditorUtility.DisplayDialog("Tips", "Init Mat Successfully !!!", "ok");
};
});
}
}