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

2024-08-23 04:52

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

这篇关于Unity编辑器扩展之Project视图扩展的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1098404

相关文章

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

数据视图(AngularJS)

<!DOCTYPE html><html ng-app="home.controller"><head><meta charset="utf-8"><title>数据视图</title><link href="page/common/css/bootstrap.min.css" rel="stylesheet"><script src="page/common/js/angular.js"></

PHP7扩展开发之数组处理

前言 这次,我们将演示如何在PHP扩展中如何对数组进行处理。要实现的PHP代码如下: <?phpfunction array_concat ($arr, $prefix) {foreach($arr as $key => $val) {if (isset($prefix[$key]) && is_string($val) && is_string($prefix[$key])) {$arr[

PHP7扩展开发之字符串处理

前言 这次,我们来看看字符串在PHP扩展里面如何处理。 示例代码如下: <?phpfunction str_concat($prefix, $string) {$len = strlen($prefix);$substr = substr($string, 0, $len);if ($substr != $prefix) {return $prefix." ".$string;} else

PHP7扩展开发之类型处理

前言 这次,我们将演示如何在PHP扩展中如何对类型进行一些操作。如,判断变量类型。要实现的PHP代码如下: <?phpfunction get_size ($value) {if (is_string($value)) {return "string size is ". strlen($value);} else if (is_array($value)) {return "array si

PHP7扩展开发之依赖其他扩展

前言 有的时候,我们的扩展要依赖其他扩展。比如,我们PHP的mysqli扩展就依赖mysqlnd扩展。这中情况下,我们怎么使用其他扩展呢?这个就是本文讲述的内容。 我们新建立一个扩展,名字叫 demo_dep , 依赖之前的say扩展。 在demo_dep扩展中,我们实现demo_say方法。这个方法调用say扩展的say方法。 代码 基础代码 确保say扩展的头文件正确安装到了php

PHP7扩展开发之函数方式使用lib库

前言 首先说下什么是lib库。lib库就是一个提供特定功能的一个文件。可以把它看成是PHP的一个文件,这个文件提供一些函数方法。只是这个lib库是用c或者c++写的。 使用lib库的场景。一些软件已经提供了lib库,我们就没必要再重复实现一次。如,原先的mysql扩展,就是使用mysql官方的lib库进行的封装。 在本文,我们将建立一个简单的lib库,并在扩展中进行封装调用。 代码 基础

PHP7扩展开发之对象方式使用lib库

前言 上一篇文章,我们使用的是函数方式调用lib库。这篇文章我们将使用对象的方式调用lib库。调用代码如下: <?php $hello = new hello(); $result = $hello->get(); var_dump($result); ?> 我们将在扩展中实现hello类。hello类中将依赖lib库。 代码 基础代码 这个扩展,我们将在say扩展上增加相关代码。sa