Unity3D 文件夹注释工具

发布于:2025-07-06 ⋅ 阅读:(11) ⋅ 点赞:(0)

前言

下面是一个完整的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();
        }
    }
}

功能说明

  1. 文件夹注释管理
  • 为Project视图中的文件夹添加自定义注释
  • 注释保存在JSON数据库中(位于Assets/Editor/FolderCommentData.json)
  • 支持编辑、删除和查看所有文件夹注释
  • 直观的UI显示
  • 在文件夹右侧显示注释图标
  • 鼠标悬停时显示注释提示框
  • 主窗口显示当前选中文件夹的注释
  • 可查看所有文件夹的注释列表
  • 主要功能
  • 添加/编辑文件夹注释
  • 清除文件夹注释
  • 显示所有注释列表
  • 手动保存数据库

使用方法

  1. 将脚本保存为FolderCommentTool.cs并放在Editor文件夹中
  2. 在Unity编辑器中通过Tools > Folder Comment Tool打开窗口
  3. 在Project视图中选择文件夹
  4. 在工具窗口中输入注释并点击"Save Comment"
  5. 在Project视图中将鼠标悬停在文件夹的注释图标上查看注释

界面特点

  • 现代化的UI设计,符合Unity编辑器风格
  • 响应式布局,适应不同窗口大小
  • 清晰的视觉层次和颜色编码
  • 直观的操作按钮和工作流程

这个工具非常适合大型项目开发,可以帮助团队更好地组织项目结构并添加重要说明,提高协作效率。

更多教学视

Unity3D​www.bycwedu.com/promotion_channels/2146264125


网站公告

今日签到

点亮在社区的每一天
去签到