关于GUID的具体理解可以参考这篇文章: https://www.cnblogs.com/zhaoqingqing/p/5823927.html
这里我们就简单理解为表示Unity文件的一个唯一标识符

使用例(代码均为其他人的代码,这里引用):

  • 引用查找:

应用场景:项目资源多得一匹,代码冗余复杂很多都没有用,想知道哪些没有用过,哪些还有用的情况下,怎么知道哪些地方用到了这些资源。

既然GUID是标识一个资源文件的唯一标识符,那么我们当然可以去通过这个GUID查找,而GUID能够存在的文件类型一般就只有.prefab(预制体)、.unity(场景)、.mat(材质)、.asset(scriptable资源)文件,所以查找也就只能是从这些文件里面查找(几乎已经是所有Unity里面会用到的地方了,足够了)所以接下来就放一段查找GUID引用的代码:

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Reflection;public class FindReferences
{[MenuItem("Assets/查找引用/同时清空控制台", false, 10)]static private void FindNot(){ClearConsole();Find();}[MenuItem("Assets/查找引用/不清空控制台", false, 10)]static private void Find(){EditorSettings.serializationMode = SerializationMode.ForceText;string path = AssetDatabase.GetAssetPath(Selection.activeObject);if (!string.IsNullOrEmpty(path)){string guid = AssetDatabase.AssetPathToGUID(path);List<string> withoutExtensions = new List<string>() { ".prefab", ".unity", ".mat", ".asset" };string[] files = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories).Where(s => withoutExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();int startIndex = 0;EditorApplication.update = delegate (){string file = files[startIndex];bool isCancel = EditorUtility.DisplayCancelableProgressBar("匹配资源中", file, (float)startIndex / (float)files.Length);if (Regex.IsMatch(File.ReadAllText(file), guid)){Debug.Log(file, AssetDatabase.LoadAssetAtPath<Object>(GetRelativeAssetsPath(file)));}startIndex++;if (isCancel || startIndex >= files.Length){EditorUtility.ClearProgressBar();EditorApplication.update = null;startIndex = 0;Debug.Log("匹配结束");}};}}[MenuItem("Assets/查找引用/同时清空控制台", true)]static private bool VFind(){string path = AssetDatabase.GetAssetPath(Selection.activeObject);return (!string.IsNullOrEmpty(path));}static private string GetRelativeAssetsPath(string path){return "Assets" + Path.GetFullPath(path).Replace(Path.GetFullPath(Application.dataPath), "").Replace('\\', '/');}static void ClearConsole(){Assembly assembly = Assembly.GetAssembly(typeof(SceneView));System.Type logEntries = assembly.GetType("UnityEditor.LogEntries");MethodInfo clearConsoleMethod = logEntries.GetMethod("Clear");clearConsoleMethod.Invoke(new object(), null);}
}

这里解释一下代码:
EditorSettings.serializationMode = SerializationMode.ForceText; 这段是设置当前的序列化模式,具体的原因我忘了,好像是说不这么设置就无法去找到确实的使用了资源的文件,这个也可以手动在Unity里面设置。

string path = AssetDatabase.GetAssetPath(Selection.activeObject);这一句是获取你选择的物体的路径的,毕竟查找引用肯定要有查找的对象啊。

string guid = AssetDatabase.AssetPathToGUID(path);一看就知道是在拿GUID了,这个应该不难理解。

然后是查找的逻辑,首先查找Application.dataPath(这个不用多解释了,不懂,百度)下的所有文件,排除非".prefab", “.unity”, “.mat”, ".asset"的文件,EditorApplication.update这段你就理解为时Editor自己的update函数就行,它后面那段委托就看做是在Update里面执行的,然后就很简单了,就是去匹配了,File.ReadAllText(file)这里并不是说真的去读file的文本文件(也可以这么说啦),这里看过上面的文章应该能懂,本质上涉及到Unity的序列化格式,反正这里你知道他能够匹配到引用的GUID就行,如果里面包含了目标的GUID,则通过AssetDatabase.LoadAssetAtPath(GetRelativeAssetsPath(file))打印出来,这里也可以直接打印文本,但是那样没办法通过点路径就找到位置,所以用这种方式更好。

可以学习的代码:
EditorSettings.serializationMode = SerializationMode.ForceText; 设置序列化模式
string.IsNullOrEmpty(path) 常用的来判断是否为空的字符串的方式(比你直接判断空或无字符来得快捷安全)
AssetDatabase.GetAssetPath(Selection.activeObject); 获得被选中物体的路径
AssetDatabase.AssetPathToGUID(path); 查找GUID
EditorApplication.update UnityEditor的Update的一个委托函数,可以在不继承自Editor的情况下去应用EditorUpdate(继承了就直接Update了,没这么多事儿)
EditorUtility.DisplayCancelableProgressBar 进度条
AssetDatabase.LoadAssetAtPath 将路径与文件所在位置对应

  • 资源替换:

应用场景:资源重复,或者想批量替换某一种UI资源的时候(这个UI资源的引用全是拖上去的时候)就可以采用直接替换GUID的形式去修改(有个我还未验证的简单方式:如果只是替换同名的资源,可以直接把原资源文件删掉,不要删除.meta,然后把新的同名资源放上去就行了,本质上应该就是GUID没有变,只是目标文件的内容变了而已)

原理应该不难理解,就是将已经用到了这个GUID的地方换成另外一个GUID就行,这里就算不贴代码大家应该都能有个思路,这里给一个我从网上一个大神哪里搜到的代码,我忘了链接,所以有知道的人可以在评论里面贴出来让大家都膜拜一下

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Linq;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections.Generic;/// <summary>
/// 解决项目中 一样的资源(名字或者路径不同)存在两份的问题  (多人做UI出现的问题, 或者美术没有管理好资源)
/// 如果是要替换资源的话, 那就直接替换好了
///
/// 以上可以这么操作的基础是,你的Unity项目内的.prefab .Unity 都可以直接用文本开看到数据,而不是乱码(二进制)。这一步很关键,怎么设置呢?
/// 打开项目Unity编辑器:Edit —-> Project Settings —-> Editor 这样就会调到你的Inspector面板的Editor Settings
/// 设置 Asset Serialization 的Mode类型为:Force Text(默认是Mixed); 这样你就能看到你的prefab文件引用了哪些贴图,字体,prefab 等资源了
/// </summary>
public class ResourcesReplace : EditorWindow
{private static ResourcesReplace _window;private Object _sourceOld;private Object _sourceNew;private string _oldGuid;private string _newGuid;private bool isContainScene = true;private bool isContainPrefab = true;private bool isContainMat = true;private bool isContainAsset = false;private List<string> withoutExtensions = new List<string>();[MenuItem("Tools/资源替换")]   // 菜单开启并点击的   处理public static void GUIDRefReplaceWin(){// true 表示不能停靠的_window = (ResourcesReplace)EditorWindow.GetWindow(typeof(ResourcesReplace), true, "引用替换 (●'◡'●)");_window.Show();}void OnGUI(){// 要被替换的(需要移除的)GUILayout.Space(20);_sourceOld = EditorGUILayout.ObjectField("旧的资源", _sourceOld, typeof(Object), true);_sourceNew = EditorGUILayout.ObjectField("新的资源", _sourceNew, typeof(Object), true);// 在那些类型中查找(.unity\.prefab\.mat)GUILayout.Space(20);GUILayout.Label("要在哪些类型中查找替换:");EditorGUILayout.BeginHorizontal();isContainScene = GUILayout.Toggle(isContainScene, ".unity");isContainPrefab = GUILayout.Toggle(isContainPrefab, ".prefab");isContainMat = GUILayout.Toggle(isContainMat, ".mat");isContainAsset = GUILayout.Toggle(isContainAsset, ".asset");EditorGUILayout.EndHorizontal();GUILayout.Space(20);if (GUILayout.Button("开始替换!")){if (EditorSettings.serializationMode != SerializationMode.ForceText){Debug.LogError("需要设置序列化模式为 SerializationMode.ForceText");ShowNotification(new GUIContent("需要设置序列化模式为 SerializationMode.ForceText"));}else if (_sourceNew == null || _sourceOld == null){Debug.LogError("不能为空!");ShowNotification(new GUIContent("不能为空!"));}else if (_sourceNew.GetType() != _sourceOld.GetType()){Debug.LogError("两种资源类型不一致!");ShowNotification(new GUIContent("两种资源类型不一致!"));}else if (!isContainScene && !isContainPrefab && !isContainMat && !isContainAsset){Debug.LogError("要选择一种 查找替换的类型");ShowNotification(new GUIContent("要选择一种 查找替换的类型"));}else   // 执行替换逻辑{StartReplace();}}}private void StartReplace(){var path = AssetDatabase.GetAssetPath(_sourceOld);_oldGuid = AssetDatabase.AssetPathToGUID(path);_newGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(_sourceNew));Debug.Log("oldGUID = " + _oldGuid + "  " + "_newGuid = " + _newGuid);withoutExtensions = new List<string>();if (isContainScene){withoutExtensions.Add(".unity");}if (isContainPrefab){withoutExtensions.Add(".prefab");}if (isContainMat){withoutExtensions.Add(".mat");}if (isContainAsset){withoutExtensions.Add(".asset");}Find();}/// <summary>/// 查找  并   替换 /// </summary>private void Find(){if (withoutExtensions == null || withoutExtensions.Count == 0){withoutExtensions = new List<string>() { ".prefab", ".unity", ".mat", ".asset" };}string[] files = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories).Where(s => withoutExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();int startIndex = 0;if (files == null || files.Length == 0){Debug.Log("没有找到 筛选的引用");return;}EditorApplication.update = delegate (){string file = files[startIndex];bool isCancel = EditorUtility.DisplayCancelableProgressBar("匹配资源中", file, (float)startIndex / (float)files.Length);var content = File.ReadAllText(file);if (Regex.IsMatch(content, _oldGuid)){Debug.Log("替换了资源的路径:" + file, AssetDatabase.LoadAssetAtPath<Object>(GetRelativeAssetsPath(file)));content = content.Replace(_oldGuid, _newGuid);File.WriteAllText(file, content);}else{Debug.Log("查看了的路径:" + file);}startIndex++;if (isCancel || startIndex >= files.Length){EditorUtility.ClearProgressBar();EditorApplication.update = null;startIndex = 0;AssetDatabase.Refresh();Debug.Log("替换结束");}};}private string GetRelativeAssetsPath(string path){return "Assets" + Path.GetFullPath(path).Replace(Path.GetFullPath(Application.dataPath), "").Replace('\\', '/');}}

同样,这里解释一下代码:
首先这里是制作了一个Eidtor窗口,涉及到Unity编辑器扩展,不懂的直接百度这个关键字就行,这里不在赘述涉及到的简单代码和逻辑。

主要代码就是Find,其他都是简单的逻辑,不难看懂,其实可以发现很多东西都和第一段代码相同,这里就挑一些不同的地方:content = content.Replace(_oldGuid, _newGuid);这里就是替换了,就如大家可能想象的那样直接replace,但是这只是改了缓存上的文本,我们还要写回去,所以File.WriteAllText(file, content);这里把所有的文本都写回原文件就行。

Unity 关于GUID的一些实用例子相关推荐

  1. 【进阶】 --- 多线程、多进程、异步IO实用例子

    [进阶] --- 多线程.多进程.异步IO实用例子:https://blog.csdn.net/lu8000/article/details/82315576 python之爬虫_并发(串行.多线程. ...

  2. C# 实现 rtc_通过Xlua实现unity热更新的一个小例子

    通过Xlua实现unity热更新的一个小例子 一.介绍 ​ 热更新是指在更新游戏资源或者逻辑的时候不需要开发者将游戏再打包.发布.玩家重新下载安装包,而是可以通过将需要更新的资源打包成AssetBun ...

  3. unity案例 mysql lua_通过Xlua实现unity热更新的一个小例子

    通过Xlua实现unity热更新的一个小例子 一.介绍 ​ 热更新是指在更新游戏资源或者逻辑的时候不需要开发者将游戏再打包.发布.玩家重新下载安装包,而是可以通过将需要更新的资源打包成AssetBun ...

  4. python装饰器实例-Python装饰器实用例子

    Python里我们经常能见到@开头的句法,也就是人们常说的装饰器(decorator).装饰器是Python非常重要的一部分,能够产出更易于维护的代码.这篇文章会给大家带来装饰器的介绍以及几个实用的例 ...

  5. Unity面试题(最新实用)

    Unity3D常见面试题 目录 C#问题 4 1.在类的构造函数前加上static会报什么错?为什么? 4 2.C# StringBuilder类型比string类型的优势是什么? 4 3.C# 函数 ...

  6. 给Linux系统/网络管理员的nmap的29个实用例子

    Nmap亦称为Network Mapper(网络映射)是一个开源并且通用的用于Linux系统/网络管理员的工具.nmap用于探查网络.执行安全扫描.网络核查并且在远程机器上找出开放端口.它可以扫描在线 ...

  7. Linux 移动或重命名文件/目录-mv 的10个实用例子

    当你想要将文件从一个位置移动到另一个地方并且不想复制它,那么mv 命令是完成这个任务的首选. 初识 mv 命令 mv 命令是一个与cp类似的命令,但是它并非创建文件或目录的复制品/副本.不管你在使用什 ...

  8. 应用DOM操作文档的一个实用例子

    DOM(Document Object Model)是表示文档(如HTML文档)和访问.操作说清楚文档的各种元素(如HTML标记和文本串)的应用程序接口(API).在DOM中,HTML文档中的各个节点 ...

  9. 【转】Linux 移动或重命名文件/目录-mv 的10个实用例子

    熟悉了 复制命令,下一个相关的命令就是 mv 命令.当你想要将文件从一个位置移动到另一个地方并且不想复制它,那么mv 命令是完成这个任务的首选. 初识 mv 命令 mv 命令是一个与cp类似的命令,但 ...

最新文章

  1. 嵌入式系统学习笔记之五-- uboot常用命令 环境变量
  2. 如何在asp.net mvc3中使用HttpStatusCode
  3. 机器学习(MACHINE LEARNING)种群竞争模型
  4. android xml引用系统资源文件,android开发教程之系统资源的使用方法 android资源文件...
  5. 全球地区资料json 含中英文 经纬度_含乳饮料行业发展趋势及市场化程度分析(附报告目录)...
  6. GDCM:gdcm::TableReader的测试程序
  7. numpy 最大值_使用 NumPy 让你的 Python 科学计算更高效
  8. redis 系列17 持久化 AOF
  9. 交叉熵的本质是极大似然估计
  10. SVNKit学习——使用低级别的API(ISVNEditor接口)直接操作Repository的目录和文件(五)...
  11. mysql dba环境验收_面对一个全新的环境,作为一个Mysql DBA,首先应该了解什么?
  12. 计算机基础考试在线搜题,计算机基础考试题库 (含答案).doc
  13. 【年终总结】你好2021,再见2020。
  14. 概念(航天):LEO,MEO,GTO,GEO,IGSO,SSO
  15. robocup2D教程
  16. Kubernetes 固定 Pod IP 地址方法
  17. c莫比乌斯函数_数论——容斥原理、莫比乌斯函数
  18. Teraterm终端登录CentOS,中文乱码问题解决方法
  19. Android: 进程保活
  20. Dijkstra算法以及与其他最短路径算法简要对比

热门文章

  1. c语言实现特征码定位内存,支持通配符
  2. XML解析以及增删改查的操作6
  3. Python+Vue计算机毕业设计新疆旅游景点信息查询网站0y596(源码+程序+LW+部署)
  4. 使用IDEA搭建 淘淘商城
  5. Petersen黎曼几何习题解答
  6. 修复Vmware虚拟网卡异常并远程连接Linux
  7. Exploring Cross-Image Pixel Contrast for Semantic Segmentation
  8. Disk Xray for Mac系统清理软件
  9. java之面向对象的英雄类
  10. 履带式机器人底盘与轮式机器人底盘有什么区别?