Unity工具—查找MD5相同的图工具

以下内容是根据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、效果


可以看到,输出了正确的结果