前言
下面是一个完整的Unity编辑器扩展工具,可以在Project视图中为文件夹添加注释并显示。这个工具支持添加、编辑和查看文件夹注释,通过图标提示和悬浮提示框增强用户体验。
对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀!
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor;
using System;
public class FolderCommentTool : EditorWindow
{
// 序列化数据结构
[System.Serializable]
private class FolderComment
{
public string guid;
public string comment;
}
[System.Serializable]
private class CommentDatabase
{
public List<FolderComment> comments = new List<FolderComment>();
}
private static CommentDatabase database;
private static string databasePath = "Assets/Editor/FolderCommentData.json";
private static Vector2 scrollPosition;
private static string newComment = "";
private static bool showAllComments = false;
private static bool showTooltip = false;
private static string hoveredGuid = "";
private static Vector2 tooltipPosition;
private static string tooltipText = "";
[MenuItem("Tools/Folder Comment Tool")]
public static void ShowWindow()
{
GetWindow<FolderCommentTool>("Folder Comments");
}
private void OnEnable()
{
LoadDatabase();
EditorApplication.projectWindowItemOnGUI += DrawFolderCommentIndicator;
}
private void OnDisable()
{
EditorApplication.projectWindowItemOnGUI -= DrawFolderCommentIndicator;
SaveDatabase();
}
private void OnGUI()
{
GUIStyle headerStyle = new GUIStyle(EditorStyles.largeLabel)
{
fontSize = 18,
fontStyle = FontStyle.Bold,
alignment = TextAnchor.MiddleCenter,
normal = { textColor = new Color(0.1f, 0.5f, 0.8f) }
};
EditorGUILayout.LabelField("Folder Comment Tool", headerStyle);
EditorGUILayout.Space(15);
// 工具栏
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
if (GUILayout.Button("Add Comment", EditorStyles.toolbarButton, GUILayout.Width(120)))
{
AddCommentToSelectedFolder();
}
showAllComments = GUILayout.Toggle(showAllComments, "Show All Comments", EditorStyles.toolbarButton, GUILayout.Width(150));
if (GUILayout.Button("Save Database", EditorStyles.toolbarButton, GUILayout.Width(120)))
{
SaveDatabase();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Selected Folder Comment", EditorStyles.boldLabel);
// 当前选中文件夹的注释编辑区
string selectedFolderGuid = GetSelectedFolderGuid();
FolderComment currentComment = database.comments.Find(c => c.guid == selectedFolderGuid);
if (selectedFolderGuid != null)
{
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("Folder: " + AssetDatabase.GUIDToAssetPath(selectedFolderGuid));
newComment = EditorGUILayout.TextArea(currentComment?.comment ?? "", GUILayout.Height(60));
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Save Comment"))
{
SaveCommentForFolder(selectedFolderGuid, newComment);
}
if (GUILayout.Button("Clear Comment"))
{
ClearCommentForFolder(selectedFolderGuid);
newComment = "";
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
else
{
EditorGUILayout.HelpBox("Select a folder in the Project view to add/edit comments", MessageType.Info);
}
// 显示所有注释
if (showAllComments && database.comments.Count > 0)
{
EditorGUILayout.Space(15);
EditorGUILayout.LabelField("All Folder Comments", EditorStyles.boldLabel);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, "box");
foreach (var comment in database.comments)
{
EditorGUILayout.BeginHorizontal();
string folderPath = AssetDatabase.GUIDToAssetPath(comment.guid);
EditorGUILayout.LabelField(Path.GetFileName(folderPath), GUILayout.Width(150));
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField(folderPath, EditorStyles.miniLabel);
EditorGUILayout.TextArea(comment.comment, GUILayout.Height(40));
EditorGUILayout.EndVertical();
if (GUILayout.Button("X", GUILayout.Width(25)))
{
database.comments.Remove(comment);
SaveDatabase();
break;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(5);
}
EditorGUILayout.EndScrollView();
}
// 绘制悬浮提示框
if (showTooltip && !string.IsNullOrEmpty(tooltipText))
{
DrawTooltip();
}
}
private static void LoadDatabase()
{
if (File.Exists(databasePath))
{
string json = File.ReadAllText(databasePath);
database = JsonUtility.FromJson<CommentDatabase>(json);
}
else
{
database = new CommentDatabase();
// 确保目录存在
string directory = Path.GetDirectoryName(databasePath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
SaveDatabase();
}
}
private static void SaveDatabase()
{
string json = JsonUtility.ToJson(database, true);
File.WriteAllText(databasePath, json);
AssetDatabase.Refresh();
}
private static void DrawFolderCommentIndicator(string guid, Rect selectionRect)
{
if (database == null) return;
// 只处理文件夹
string path = AssetDatabase.GUIDToAssetPath(guid);
if (!AssetDatabase.IsValidFolder(path)) return;
// 查找注释
FolderComment comment = database.comments.Find(c => c.guid == guid);
if (comment == null || string.IsNullOrEmpty(comment.comment)) return;
// 调整图标位置
Rect iconRect = new Rect(selectionRect);
iconRect.x = selectionRect.xMax - 20;
iconRect.width = 16;
iconRect.height = 16;
iconRect.y += 2;
// 绘制注释图标
GUIContent iconContent = EditorGUIUtility.IconContent("d_TextAsset Icon");
GUI.Label(iconRect, iconContent);
// 鼠标悬停检测
Event evt = Event.current;
if (iconRect.Contains(evt.mousePosition))
{
// 显示提示
showTooltip = true;
hoveredGuid = guid;
tooltipPosition = GUIUtility.GUIToScreenPoint(evt.mousePosition);
tooltipText = comment.comment;
// 重绘使提示框保持显示
EditorWindow.mouseOverWindow?.Repaint();
}
else if (hoveredGuid == guid)
{
showTooltip = false;
}
}
private void DrawTooltip()
{
if (string.IsNullOrEmpty(tooltipText)) return;
// 设置提示框样式
GUIStyle tooltipStyle = new GUIStyle("helpbox")
{
padding = new RectOffset(10, 10, 10, 10),
wordWrap = true,
fontSize = 12,
normal = { textColor = EditorGUIUtility.isProSkin ? Color.white : Color.black }
};
// 计算提示框大小
float width = Mathf.Min(300, position.width - 40);
GUIContent content = new GUIContent(tooltipText);
Vector2 size = tooltipStyle.CalcSize(content);
size.x = width;
size.y = tooltipStyle.CalcHeight(content, width) + 10;
// 定位提示框
Rect tooltipRect = new Rect(tooltipPosition.x + 15, tooltipPosition.y + 15, size.x, size.y);
// 确保提示框在屏幕内
if (tooltipRect.xMax > Screen.currentResolution.width)
tooltipRect.x = Screen.currentResolution.width - tooltipRect.width - 10;
if (tooltipRect.yMax > Screen.currentResolution.height)
tooltipRect.y = Screen.currentResolution.height - tooltipRect.height - 10;
// 绘制背景和边框
GUI.Box(tooltipRect, "", "window");
// 绘制文本
GUI.Label(tooltipRect, tooltipText, tooltipStyle);
}
private static string GetSelectedFolderGuid()
{
if (Selection.assetGUIDs.Length == 0) return null;
string path = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);
return AssetDatabase.IsValidFolder(path) ? Selection.assetGUIDs[0] : null;
}
private static void AddCommentToSelectedFolder()
{
string guid = GetSelectedFolderGuid();
if (guid == null)
{
EditorUtility.DisplayDialog("No Folder Selected", "Please select a folder in the Project window", "OK");
return;
}
SaveCommentForFolder(guid, "New comment...");
newComment = "New comment...";
}
private static void SaveCommentForFolder(string guid, string comment)
{
FolderComment existing = database.comments.Find(c => c.guid == guid);
if (existing != null)
{
existing.comment = comment;
}
else
{
database.comments.Add(new FolderComment { guid = guid, comment = comment });
}
SaveDatabase();
}
private static void ClearCommentForFolder(string guid)
{
FolderComment existing = database.comments.Find(c => c.guid == guid);
if (existing != null)
{
database.comments.Remove(existing);
SaveDatabase();
}
}
}
功能说明
- 文件夹注释管理:
- 为Project视图中的文件夹添加自定义注释
- 注释保存在JSON数据库中(位于Assets/Editor/FolderCommentData.json)
- 支持编辑、删除和查看所有文件夹注释
- 直观的UI显示:
- 在文件夹右侧显示注释图标
- 鼠标悬停时显示注释提示框
- 主窗口显示当前选中文件夹的注释
- 可查看所有文件夹的注释列表
- 主要功能:
- 添加/编辑文件夹注释
- 清除文件夹注释
- 显示所有注释列表
- 手动保存数据库
使用方法
- 将脚本保存为
FolderCommentTool.cs
并放在Editor
文件夹中 - 在Unity编辑器中通过
Tools > Folder Comment Tool
打开窗口 - 在Project视图中选择文件夹
- 在工具窗口中输入注释并点击"Save Comment"
- 在Project视图中将鼠标悬停在文件夹的注释图标上查看注释
界面特点
- 现代化的UI设计,符合Unity编辑器风格
- 响应式布局,适应不同窗口大小
- 清晰的视觉层次和颜色编码
- 直观的操作按钮和工作流程
这个工具非常适合大型项目开发,可以帮助团队更好地组织项目结构并添加重要说明,提高协作效率。
更多教学视