Unity编辑器扩展之Project视图扩展

内容将会持续更新,有错误的地方欢迎指正,谢谢!
 

Unity编辑器扩展之Project视图扩展
     
TechX 坚持将创新的科技带给世界!

拥有更好的学习体验 —— 不断努力,不断进步,不断探索
TechX —— 心探索、心进取!

助力快速掌握 Project视图 编辑器扩展

为初学者节省宝贵的学习时间,避免困惑!



文章目录

  • 一、EditorApplication.projectChanged 之自动更新资源依赖报告
  • 二、EditorApplication.projectWindowItemOnGUI 之标记资源大小
  • 三、UnityEditor.AssetModificationProcessor 之资源修改处理器
    • 3.1、OnWillCreateAsset 之自动添加资源模板
    • 3.2、OnWillSaveAssets
    • 3.3、OnWillMoveAsset
    • 3.4、OnWillDeleteAsset


一、EditorApplication.projectChanged 之自动更新资源依赖报告


使用 EditorApplication.projectChanged 可以在项目资源发生变化时自动执行一些功能。下面展示如何使用这个事件在Unity项目中实现一个简单但实用的功能:自动更新资源依赖报告。

当项目资源变化时自动生成一份资源依赖报告,列出哪些资源被哪些其他资源依赖。这在进行资源优化或清理时非常有用。

using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.IO;[InitializeOnLoad]
public static class DependencyReportGenerator
{private const string ReportPath = "Assets/DependencyReport.txt";static DependencyReportGenerator(){EditorApplication.projectChanged += OnProjectChanged;}private static void OnProjectChanged(){Debug.Log("项目资源发生变化,正在生成依赖报告...");Dictionary<string, List<string>> dependencyMap = GenerateDependencys();GenerateReport(dependencyMap);Debug.Log("依赖报告生成完毕。");}/// <summary>/// 生成依赖项/// </summary>private static Dictionary<string, List<string>> GenerateDependencys(){string[] allAssetGuids = AssetDatabase.FindAssets("");Dictionary<string, List<string>> dependencyMap = new Dictionary<string, List<string>>();foreach (string guid in allAssetGuids){string assetPath = AssetDatabase.GUIDToAssetPath(guid);string[] dependencies = AssetDatabase.GetDependencies(assetPath, false);foreach (string dependency in dependencies){if (!dependencyMap.ContainsKey(dependency)){dependencyMap[dependency] = new List<string>();}dependencyMap[dependency].Add(assetPath);}}return dependencyMap;}/// <summary>/// 生成报告/// </summary>private static void GenerateReport(Dictionary<string, List<string>> dependencyMap){using (StreamWriter writer = new StreamWriter(ReportPath)){foreach (var kvp in dependencyMap){writer.WriteLine($"资源:{kvp.Key}");writer.WriteLine("被以下资源依赖:");foreach (string dependent in kvp.Value){writer.WriteLine($" - {dependent}");}writer.WriteLine();}}}
}

资源依赖报告列出了每个资源被哪些其他资源依赖,帮助开发者了解资源之间的关系。

生成的资源依赖报告文件存储在 Assets/DependencyReport.txt 中。

在这里插入图片描述



二、EditorApplication.projectWindowItemOnGUI 之标记资源大小


EditorApplication.projectWindowItemOnGUI 是一个非常实用的 API,它允许你在 Unity 的 Project 窗口中自定义显示项目资源的图标、标签或其他信息。通过这个方法,可以实现一些方便开发者查看和管理资源的功能。

我们可以通过 EditorApplication.projectWindowItemOnGUI 实现一个功能:在 Project 窗口中直接显示每个资源的文件大小。这在管理大型项目时非常有用,可以帮助开发者快速识别占用空间较大的资源并进行优化。

using UnityEditor;
using UnityEngine;
using System.IO;[InitializeOnLoad]
public static class AssetSizeDisplay
{static AssetSizeDisplay(){EditorApplication.projectWindowItemOnGUI += OnProjectWindowItemOnGUI;}private static void OnProjectWindowItemOnGUI(string guid, Rect selectionRect){// 获取资源路径string assetPath = AssetDatabase.GUIDToAssetPath(guid);// 仅处理文件,不处理文件夹if (File.Exists(assetPath)){// 获取文件大小long fileSize = new FileInfo(assetPath).Length;string fileSizeStr = GetReadableFileSize(fileSize);// 根据文件大小设置颜色Color labelColor = GetColorByFileSize(fileSize);// 在资源右侧显示文件大小Rect sizeRect = new Rect(selectionRect.xMax - 50, selectionRect.y, 75, selectionRect.height);EditorGUI.DrawRect(selectionRect, labelColor * 0.2f); // 背景色(较浅)EditorGUI.LabelField(sizeRect, fileSizeStr, new GUIStyle(EditorStyles.label) { normal = { textColor = labelColor } });}}/// <summary>/// 将文件大小转换为易读的格式/// </summary>/// <param name="size"></param>/// <returns></returns>private static string GetReadableFileSize(long size){string[] sizes = { "B", "KB", "MB", "GB" };int order = 0;while (size >= 1024 && order < sizes.Length - 1){order++;size = size / 1024;}return $"{size:0.#} {sizes[order]}";}/// <summary>/// 根据文件大小返回不同的颜色/// </summary>/// <param name="size"></param>/// <returns></returns>private static Color GetColorByFileSize(long size){if (size > 100 * 1024 * 1024) // 大于 100MBreturn Color.red;if (size > 10 * 1024 * 1024)  // 大于 10MBreturn new Color(1f, 0.5f, 0f); // 橙色if (size > 1 * 1024 * 1024)   // 大于 1MBreturn Color.yellow;return Color.green;            // 小于 1MB}
}

在 Project 窗口中,每个文件资源的右侧都会显示其文件大小。这样,开发者可以在不打开资源详情的情况下,快速了解各资源的占用空间,从而有助于进行优化和管理。并且根据文件大小用不同颜色标记资源。

在这里插入图片描述



三、UnityEditor.AssetModificationProcessor 之资源修改处理器


UnityEditor.AssetModificationProcessor 是 Unity 编辑器提供的一个抽象类,它允许开发者在编辑器中拦截和处理与资源(Assets)相关的事件。

通过继承和实现这个类,开发者可以编写自定义逻辑来响应资源的创建、保存、移动和删除等操作。此类在需要对资源操作进行管理、限制或自动化时非常有用。

public class AssetEventEditor : UnityEditor.AssetModificationProcessor
{//监听"资源即将被创建"事件public static void OnWillCreateEdit(string path){Debug.LogFormat("创建资源的路径:{0}", path);}//监听"资源即将被保存"事件public static string[] OnWillSaveAssets(string[] paths) {Debug.LogFormat("保存资源的路径:{0}",string.Join(",",paths));return paths;}//监听"资源即将被移动"事件  DidNotMove表示可以移动,DidMove表示不可以移动public static AssetMoveResult OnWillMoveAsset(string oldPath,string newPath) {Debug.LogFormat("资源从路径{0}移动到路径{1}", oldPath,newPath);return AssetMoveResult.DidNotMove;}//监听"资源即将被删除"事件 DidNotDelete表示可以移动,DidDelete表示不可以移动public static AssetDeleteResult OnWillDeleteAsset(string assetPath) {Debug.LogFormat("资源从路径{0}删除", assetPath);return AssetDeleteResult.DidNotDelete;}

3.1、OnWillCreateAsset 之自动添加资源模板


OnWillCreateAsset 方法在 Unity 中用于拦截和处理即将创建的资源事件。

当一个新的资源(如脚本、预制件、纹理等)被创建时,OnWillCreateAsset 方法会被调用。

这个方法可以让你在资源创建之前执行一些自定义操作。

public static void OnWillCreateAsset(string path)
{path = path.Replace(".meta", "");if (path.EndsWith(".cs")){string fullPath = Path.Combine(Directory.GetCurrentDirectory(), path);string fileContent = File.ReadAllText(fullPath);// 插入默认命名空间fileContent = fileContent.Replace("#SCRIPTNAME#", Path.GetFileNameWithoutExtension(path));fileContent = string.Join("\n", fileContent.Split('\n').Select(item => "\t" + item));fileContent = "using UnityEngine;\n\nnamespace MyNamespace\n{\n" + fileContent + "\n}".TrimStart('\t');File.WriteAllText(fullPath, fileContent);AssetDatabase.Refresh();Debug.LogFormat("创建脚本时自动添加了命名空间:{0}", path);}
}

在这个例子中,OnWillCreateAsset 方法在创建脚本的时候被调用,它被用来为新创建的 C# 脚本文件添加命名空间并格式化代码。这种自动化操作可以提高代码的一致性和开发效率。

在这里插入图片描述


3.2、OnWillSaveAssets


OnWillSaveAssets 在Unity中用于在保存资产(例如场景、预制体)之前执行特定的操作。

这个方法可以帮助你在资产保存之前进行自定义的检查和处理。通过在这个方法中执行适当的逻辑,可以确保资产的质量和一致性,从而提高开发效率并减少潜在问题。

public static string[] OnWillSaveAssets(string[] paths){foreach (string path in paths){if (path.EndsWith(".prefab") || path.EndsWith(".unity")){CheckForMissingReferences(path);}}return paths;}private static void CheckForMissingReferences(string path){// 加载资源对象,处理预制件或场景文件Object asset = AssetDatabase.LoadAssetAtPath<Object>(path);// 检查场景文件if (asset is SceneAsset){Scene scene = EditorSceneManager.OpenScene(path, OpenSceneMode.Additive);CheckSceneForMissingReferences(scene);}// 检查预制件else if (asset is GameObject go){CheckGameObjectForMissingReferences(go, path);}}private static void CheckSceneForMissingReferences(Scene scene){foreach (GameObject rootObj in scene.GetRootGameObjects()){CheckGameObjectForMissingReferences(rootObj, scene.path);}}private static void CheckGameObjectForMissingReferences(GameObject go, string path){if (PrefabUtility.IsPartOfAnyPrefab(go) && PrefabUtility.GetCorrespondingObjectFromSource(go) == null){Debug.LogError($"预制体引用丢失 对象:{GetGameObjectPath(go)},路径: {path}", go);}foreach (Component component in go.GetComponentsInChildren<Component>(true)){if (component == null){Debug.LogError($"脚本引用丢失 对象:{GetGameObjectPath(go)},路径: {path}", go);}}}private static string GetGameObjectPath(GameObject go){if (go.transform.parent == null) return go.name;return GetGameObjectPath(go.transform.parent.gameObject) + "/" + go.name;}

在这个例子中,OnWillSaveAssets方法在在保存场景和预制体时检查是否存在丢失的脚本和预制体引用,并在控制台输出相关警告。

3.3、OnWillMoveAsset


OnWillMoveAsset 在 Unity 中用于当资源(如脚本、预制件等)即将被移动到新路径时调用。

它允许开发者在移动资源前执行一些自定义逻辑,并决定是否允许资源移动。

//监听"资源即将被移动"事件public static AssetMoveResult OnWillMoveAsset(string oldPath, string newPath)
{UpdateScriptPaths(oldPath, newPath);return AssetMoveResult.DidNotMove; // 允许移动
}
private static void UpdateScriptPaths(string oldPath, string newPath)
{// 查找所有脚本文件并更新路径string[] scripts = AssetDatabase.FindAssets("t:Script");foreach (string scriptGUID in scripts){string scriptPath = AssetDatabase.GUIDToAssetPath(scriptGUID);string scriptContent = File.ReadAllText(scriptPath);if (scriptContent.Contains(oldPath)){scriptContent = scriptContent.Replace(oldPath, newPath);File.WriteAllText(scriptPath, scriptContent);AssetDatabase.Refresh();Debug.LogFormat("更新脚本中的资源路径: {0}", scriptPath);}}
}

当资源移动到新位置时,项目中的脚本可能依赖于该资源的路径。通过在 OnWillMoveAsset 方法中更新脚本中的路径引用,可以确保项目正常运行,避免路径失效导致的错误。

3.4、OnWillDeleteAsset


OnWillDeleteAsset 在 Unity 中用于在资源(如脚本、预制件、材质等)即将被删除时进行拦截和处理。

通过这个方法,开发者可以在资源被删除前执行自定义逻辑,比如弹出确认对话框、记录日志,甚至阻止资源删除。

public static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions assetOptions)
{if (assetPath.StartsWith("Assets/ImportantAssets/")){Debug.Log(assetPath);if (!EditorUtility.DisplayDialog("警告", $"你确定要删除重要资源 {assetPath} 吗?", "确定", "取消")){Debug.LogWarning($"已取消删除重要资源:{assetPath}");return AssetDeleteResult.DidDelete; // 阻止删除}}Debug.LogFormat("资源 {0} 被删除", assetPath);return AssetDeleteResult.DidNotDelete; // 允许删除
}

通过自定义逻辑,开发者可以确保重要资源不会被轻易删除,并在删除前执行必要的检查和确认。这个方法对于项目管理和资源保护非常有用。

在这里插入图片描述





TechX —— 心探索、心进取!

每一次跌倒都是一次成长

每一次努力都是一次进步


END
感谢您阅读本篇博客!希望这篇内容对您有所帮助。如果您有任何问题或意见,或者想要了解更多关于本主题的信息,欢迎在评论区留言与我交流。我会非常乐意与大家讨论和分享更多有趣的内容。
如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。
在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/409549.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一家物流装备企业终止,业绩下滑严重,恐不符合创业板新上市标准

鸿安机械终止的原因如下&#xff1a;首先&#xff0c;报告期内鸿安机械的营业收入和净利润出现下滑趋势&#xff0c;公司最近一年净利润恐不达标&#xff0c;或许不能满足创业板更新的第一套上市标准&#xff1b;其次&#xff0c;鸿安机械经营业绩对比同行业可比公司&#xff0…

智能优化特征选择|基于鹦鹉优化(2024年新出优化算法)的特征选择(分类器选用的是KNN)研究Matlab程序 【优化算法可以替换成其他优化方法】

智能优化特征选择|基于鹦鹉优化&#xff08;2024年新出优化算法&#xff09;的特征选择&#xff08;分类器选用的是KNN&#xff09;研究Matlab程序 【优化算法可以替换成其他优化方法】 文章目录 一、PO基本原理PO基本原理基本流程示例应用 二、实验结果三、核心代码四、代码获…

gitlab使用教程

一、定义 pycharm 克隆代码pycharm 克隆分支type 提交指令使用可视化界面SourceTreepycharm中git 基本使用获取和拉取的区别&#xff0c;update project 区别sourceTree 回退版本sourceTree 回滚代码 二、实现 教程&#xff1a; https://liaoxuefeng.com/books/git/gui/inde…

在DDD中应用模式

深层模型和柔性设计并非唾手可得。要想取得进展&#xff0c;必须学习大量领域知识并进行充分的讨论&#xff0c;还需要经历大量的尝试和失败。但有时我们也能从中获得一些优势。一位经验丰富的开发人员在研究领域问题时&#xff0c;如果发现了他所熟悉的某种职责或某个关系网&a…

Nosql数据库redis集群配置详解

一、Redis的安装 环境介绍&#xff1a; 一主双从&#xff1a;10&#xff08;redis-node1&#xff09;主&#xff0c;20&#xff08;redis-node2&#xff09; 30&#xff08;redis-node3&#xff09;从——使用的是红帽9.1系统 源码安装redis [rootredis-node1 ~]# tar zxf red…

前端常见问题

一、<!DOCTYPE html>作用 <!DOCTYPE>是html文档的第一行&#xff0c;用于声明文档的类型&#xff0c;它会告诉浏览器要用哪一种HTML规范来渲染文档&#xff0c;确保正确渲染页面。 二、src与 href 的区别 &#xff08;一&#xff09;、请求资源类型的不同 在请…

女明星玩乙游,为何会推动国乙玩家“世纪大和解”?

“震惊&#xff01;叠姐和光姐竟然世纪大和解了。” 这件在国乙圈匪夷所思、想都不敢想的事&#xff0c;竟然在一位女明星的推动下发生了&#xff0c;也因此诞生了国乙圈的“8.22事件”。 事情的起因是女艺人乃万在社交平台上发布了乙游相关言论&#xff0c;引起了乙游玩家不…

Spring--三级缓存机制

一、什么是三级缓存 就是在Bean生成流程中保存Bean对象三种形态的三个Map集合&#xff0c;如下&#xff1a; // 一级缓存Map 存放完整的Bean&#xff08;流程跑完的&#xff09; private final Map<String, Object> singletonObjects new ConcurrentHashMap(256);// 二…

USB3.2 摘录(九)

系列文章目录 USB3.2 摘录&#xff08;一&#xff09; USB3.2 摘录&#xff08;二&#xff09; USB3.2 摘录&#xff08;三&#xff09; USB3.2 摘录&#xff08;四&#xff09; USB3.2 摘录&#xff08;五&#xff09; USB3.2 摘录&#xff08;六&#xff09; USB3.2 摘录&…

页面设计任务 商品详情页(带评论区)

目录 效果图&#xff1a; 任务描述 源码&#xff1a; 详细讲解&#xff1a; 1.产品信息部分 2.用户评论区域 效果图&#xff1a; 任务描述 页面结构: 页面应包括一个标题部分、一个产品展示区和一个客户评价区。使用图片展示产品&#xff0c;并添加描述。客户评价区展示一…

IP代理池学习记录

免责声明 本文仅供学习和研究目的使用。所提供的信息和技术仅限于合规和合法的使用场景。请读者在应用相关技术时遵守法律法规&#xff0c;尊重他人的数据隐私和网站使用条款。本文作者对因使用本文信息而产生的任何法律责任或损失不承担责任。 1、初识IP代理池 概述&#xff…

如何使用ssm实现基于SSM的社区物业管理系统的设计与实现+vue

TOC ssm223基于SSM的社区物业管理系统的设计与实现vue 绪论 1.1 研究背景 现在大家正处于互联网加的时代&#xff0c;这个时代它就是一个信息内容无比丰富&#xff0c;信息处理与管理变得越加高效的网络化的时代&#xff0c;这个时代让大家的生活不仅变得更加地便利化&…

Redis—缓存机制

Redis 缓存机制 1. 缓存三兄弟1.1 缓存击穿1.2 缓存穿透1.3 缓存雪崩 2. 布隆过滤器3. 缓存和数据库数据一致性3.1 缓存更新策略3.2 缓存不一致处理 4. 热点 key4.1 热点 key 处理4.2 热点 key 重建 5. 缓存预热 Redis&#xff0c;一个轻量级的开源内存数据结构存储系统&#x…

Redis计数器:数字的秘密

文章目录 Redis计数器incr 指令用户计数统计用户统计信息查询缓存一致性 小结 技术派项目源码地址 : Gitee :技术派 - https://gitee.com/itwanger/paicodingGithub :技术派 - https://github.com/itwanger/paicoding 用户的相关统计信息 文章数&#xff0c;文章总阅读数&am…

go设计模式——单例模式

概念 单例是一种创建型设计模式&#xff0c;它确保一个类在整个程序运行期间只有一个实例&#xff0c;并提供一个全局访问点来使用该实例。虽然单例模式在某些情况下非常有用&#xff0c;例如管理全局配置、日志记录或资源共享&#xff0c;但它也带来了与全局变量相似的问题。…

redis面试(二十三)写锁释放

先加了写锁&#xff0c;后面再次加写锁或者读锁 anyLock: { “mode”: “write”, “UUID_01:threadId_01:write”: 2, “UUID_01:threadId_01”: 1 } 写锁的释放lua脚本在这里 RedissonWriteLock.unlockInnerAsync() 比如说现在的参数是这 KEYS[1] anyLock KEYS[2] redi…

SQL手工注入漏洞测试(MongoDB数据库)靶场通关攻略

构造数据回显 });return ({title:1,content:2 成功回显1,2&#xff0c;接下来我们开始尝试查询数据库 });return({title:tojson(db),content:2 得到之后我们就可以继续查询他的表名了 });return({title:tojson(db.getCollectionNames()),content:2 最后我们就可以爆出他表里的数…

宝塔面板配置FTP服务并安装内网穿透实现无公网IP远程连接

文章目录 前言1. Linux安装Cpolar2. 创建FTP公网地址3. 宝塔FTP服务设置4. FTP服务远程连接小结 5. 固定FTP公网地址6. 固定FTP地址连接 前言 本文主要介绍宝塔FTP文件传输服务如何搭配内网穿透工具&#xff0c;实现随时随地远程连接局域网环境搭建的宝塔FTP文件服务并进行文件…

ssrf实现.SSH未创建写shell

一、介绍SSRF漏洞 SSRF (Server-Side Request Forgery,服务器端请求伪造)是一种由攻击者构造请求&#xff0c;由服务端发起请求的安全漏洞。一般情况下&#xff0c;SSRF攻击的目标是外网无法访问的内部系统(正因为请求是由服务端发起的&#xff0c;所以服务端能请求到与自身相…

C语言基础——函数详解

目录 函数的概述 1 函数的概念 2 函数的意义 函数的定义和使用 1 函数的定义 2 函数的调用 2.1 在同一文件中函数定义后函数调用 2.2 在同一文件中函数定义前函数调用 2.3 调用其它文件中定义的函数 2.3.1 在函数调用文件中进行声明 2.3.2 在头文件中进行函数的声明 函…