Unity中检查重复的资源

目的:
检查Unity中资源是否重复,例如有两张贴图,明明是一张,却被复制为两份放在工程中,名字或者所在目录位置不同,这对于资源管理来说是很浪费的。因此需要写一个检查工具来检查项目中是否存在重复的资源。


思路:

Unity引擎内部对资源的管理是否有一个唯一标识,通过这个唯一标识来检查是否有多个资源的此标识相同。


相关知识:

1.Guid:

Unity会为每一个加入到Assets文件夹中的文件,创建一个同级同名的.meta文件,虽然文件类型的不同会影响这个.meta的具体内容,但它们都包含一个用来标记文件身份的File GUID

文件GUID提供了文件存储位置的抽象,这样一个文件GUID就对应一个具体的文件,因此我们才能随意移动这个文件而不破坏所有相关Object对这个文件的引用,而如果这个meta文件和物体不对应(比如我们SVN提交的时候没有提交修改的Meta文件),那么这个文件的引用就会丢失,造成不可预知的错误。

总结:存储了此文件和其他文件之间的引用关系

2.Localid:

标识了文件内部各个文件之间的引用关系,比如一个Prefab内部的各个gameObject之间的引用关系

3.InstanceId:

Guid和Localid更像是为了文件系统的管理而设计的,那么我们在unity中实际编写代码或者引擎对object进行管理的时候每次去获取这两个大字符串显然是效率很低的,因此Unity在对象层面又通过这两个Id设计了InstanceId。简单来说,我们在工程中可以通过InstanceId来获取任何一个Object的实例。这个Id通过GetInstanceID获得,返回物体的实例ID,即使是同一个Prefab,实例化出的不同GameObject的InstanceId也是不一样的

 

4.MD5

unity内部通过一种算法来计算资源文件的MD5码(一个字符串),这种方法类似于哈希,将不同文件计算出不同的MD5码,但不同于哈希值的计算,我们希望MD5最好永远不要重复(哈希值计算会出现重复冲突的情况),MD5一般被认为是Unity中区分不同文件的唯一标识,那么有人肯定会疑问,万一这个值真的重复了呢。不错,确实有比较厉害的黑客可以破解Unity所使用的的计算算法,使得不同的资源文件产生相同的MD5码,不过这是非常极端的情况。我们知道热更新的时候也会用到MD5码,来标识我们需要更新哪个文件,那么在这个过程我们最好是对MD5码进行加密的,以防有恶意软件攻击我们热更新的文件。

总结:资源文件的唯一标识,即使是同一个文件(不同名字,目录)这个值也是相同的,因此可以作为我们检查资源是否重复的比较标识


检查工具

思路:计算特定目录下文件的MD5码,将其存入字典中,如果字典中已经存在此key值,说明资源重复

关键:getTextureByte(),根据路径资源文件计算MD5码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
using UnityEngine;
 
using System.Collections.Generic;
 
using System.IO;
 
using UnityEditor;
 
using System.Security.Cryptography;
 
public class ResCheckTool
 
{
 
    // md5和guidId不相同
 
    [MenuItem("Tools/Find Repeat", false, 10)]
 
    static private void Check()
 
    {
 
        // 定义查找路径
 
        string[] guids = Directory.GetFiles("Assets/Resources/", "*.*", SearchOption.AllDirectories);
 
        // 以MD5值为key的字典
 
        Dictionary<string, string> checkDic = new Dictionary<string, string>();
 
        string fileMd5 = string.Empty;
 
        for (int i = 0, count = guids.Length; i < count; i++)
 
        {
 
            // 过滤meta文件
 
            if (!guids[i].EndsWith(".meta"))
 
            {
 
                MD5 md5 = MD5.Create();
 
                byte[] md5bytes = md5.ComputeHash(getTextureByte(guids[i]));
 
                fileMd5 = System.BitConverter.ToString(md5bytes).Replace("-", "").ToLower();
 
                if (!checkDic.ContainsKey(fileMd5))
 
                {
 
                    checkDic.Add(fileMd5, guids[i]);
 
                }
 
                else
 
                {
 
                    Debug.Log("重复资源路径:" + guids[i] + "重复资源md5:" + fileMd5);
 
                }
 
            }
 
        }
 
    }
 
    /// <summary>
 
    /// 根据图片路径返回字节流,基本不会重复
 
    /// </summary>
 
    /// <param name="texturePath"></param>
 
    /// <returns></returns>
 
    static private byte[] getTextureByte(string assetsPath)
 
    {
 
        FileStream file = new FileStream(assetsPath, FileMode.Open);
 
        byte[] txByte = new byte[file.Length];
 
        file.Read(txByte, 0, txByte.Length);
 
        file.Close();
 
        return txByte;
 
    }
 
}

  https://www.jianshu.com/p/01a41a095a5c

posted @   钢与铁  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· 10亿数据,如何做迁移?
· 推荐几款开源且免费的 .NET MAUI 组件库
· c# 半导体/led行业 晶圆片WaferMap实现 map图实现入门篇
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
点击右上角即可分享
微信分享提示