以下内容是根据Unity 2020.1.0f1版本进行编写的
Unity工具---查找MD5相同的图工具
1、目的
在项目中,很多时候会遇到需要复用一个图片资源的情况(这里指小图),如果直接在预制里引用,那么打开该界面时会把其它功能的图集也加载到内存中。考虑到性能影响,为了防止打开某界面或某功能时,加载其它功能图集导致内存消耗增大,我一般会复制一个图片,并在资源命名后面加上_copy后缀。
但随着该图片引用次数的增多,这时候应该将其移动到公共图集,并且删掉其它全部的复制资源,并将资源引用改为移动到公共图集的资源。也有可能美术人员也会多次复制同一个资源,同样的,当引用次数过多时,应该放置到公共资源中。
这时候,就需要一个工具检测相同的资源。因为复制资源的MD5是相同的,所以我这里只需要实现一个检测项目中全部资源的MD5,并将相同的MD5记录并输出出来,就可以知道哪些资源需要移动到公共资源了。
2、实现
话不多说直接上代码:
csharp
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using UnityEditor;
using UnityEngine;
public class CheckSpritesRepeatMD5
{
private static string directoryPath = Application.dataPath + "/sprites";
[MenuItem("Tools/查找MD5相同的图", false, 20)]
public static Dictionary<string, List<string>> SearchMD5RepeatSprites()
{
List<string> files = new List<string>();
SeachFile(directoryPath, files, new string[] { ".jpg", ".png" });
Dictionary<string, List<string>> md5RepeatDictionary = new Dictionary<string, List<string>>();
Dictionary<string, string> md5Dictionary = new Dictionary<string, string>();
foreach (var assetPath in files)
{
string md5 = GetMD5Hash(assetPath);
if (md5Dictionary.ContainsKey(md5))
{
if (md5RepeatDictionary.ContainsKey(md5))
{
List<string> assetPathList = md5RepeatDictionary[md5];
assetPathList.Add(assetPath);
md5RepeatDictionary[md5] = assetPathList;
}
else
{
List<string> assetPathList = new List<string>();
assetPathList.Add(md5Dictionary[md5]);
assetPathList.Add(assetPath);
md5RepeatDictionary.Add(md5, assetPathList);
}
}
else
{
md5Dictionary.Add(md5, assetPath);
}
}
Debug.LogError("MD5重复资源: ");
foreach (var assetPathList in md5RepeatDictionary.Values)
{
foreach (var assetPath in assetPathList)
{
Debug.LogError(assetPath);
}
Debug.LogError("------------------------------------------------------------------------------------------------------------------------------------------------------------------");
}
AssetDatabase.Refresh();
Debug.LogError("完成");
return md5RepeatDictionary;
}
public static void SeachFile(string path, List<string> files, string[] extensions)
{
if (Directory.Exists(path))
{
DirectoryInfo di = new DirectoryInfo(path);
FileSystemInfo[] fsInfos = di.GetFileSystemInfos();
bool isSkip;
foreach (FileSystemInfo fsInfo in fsInfos)
{
isSkip = true;
if (fsInfo is DirectoryInfo)
{
SeachFile(fsInfo.FullName, files, extensions);
}
if (fsInfo.Name.Contains(".meta"))
{
continue;
}
foreach (string extension in extensions)
{
if (fsInfo.Name.Contains(extension))
{
isSkip = false;
break;
}
}
if (!isSkip)
{
string fileN = fsInfo.FullName;
string ss = "Assets" + fileN.Replace("\\", "/").Replace(Application.dataPath, "");
if (!files.Contains(ss))
{
files.Add(ss);
}
}
}
}
}
public static string GetMD5Hash(string filePath)
{
MD5 md5 = new MD5CryptoServiceProvider();
return BitConverter.ToString(md5.ComputeHash(File.ReadAllBytes(filePath))).Replace("-", "").ToLower();
}
}
核心方法就是GetMD5Hash,通过这个方法获取到某个文件的md5值,然后逐个对比就可以了。
3、效果
可以看到,输出了正确的结果