diff --git a/MeowMentDebugTool.slnx b/MeowMentDebugTool.slnx
index 4be91a3..bdc551b 100644
--- a/MeowMentDebugTool.slnx
+++ b/MeowMentDebugTool.slnx
@@ -1,5 +1,5 @@
-
+
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/BUGFIX_REBUILD_LOOP.md b/Packages/com.bywaystudios.meowmentdebugtool/BUGFIX_REBUILD_LOOP.md
new file mode 100644
index 0000000..0592dcb
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/BUGFIX_REBUILD_LOOP.md
@@ -0,0 +1,215 @@
+# Console模块错误修复说明
+
+## 🐛 已修复的问题
+
+### 1. Rebuild Loop 错误
+
+**问题描述**:
+```
+Trying to remove/add Background (UnityEngine.UI.Image) from/to rebuild list
+while we are already inside a rebuild loop. This is not supported.
+```
+
+**原因**:
+- 在 `OnLogMessageReceived` 回调中立即调用 `RefreshLogDisplay()` 刷新UI
+- 在Unity的Canvas rebuild循环中修改UI元素会触发此错误
+- `Canvas.ForceUpdateCanvases()` 在初始化时也会导致rebuild loop
+
+**修复方案**:
+
+#### ConsoleModule.cs
+1. ✅ **延迟刷新机制**: 添加 `needRefresh` 标志,不在回调中立即刷新UI
+```csharp
+private bool needRefresh = false;
+
+// 在OnLogMessageReceived中
+needRefresh = true; // 标记需要刷新
+
+// 在Update中
+if (needRefresh)
+{
+ needRefresh = false;
+ RefreshLogDisplay(); // 延迟到下一帧刷新
+}
+```
+
+2. ✅ **滚动位置延迟设置**: 使用帧计数延迟设置滚动位置
+```csharp
+private int lastRefreshFrame = -1;
+
+// 只在刷新后的第2帧设置滚动位置
+if (lockScroll && Time.frameCount > lastRefreshFrame + 1)
+{
+ logScrollRect.verticalNormalizedPosition = 0f;
+}
+```
+
+3. ✅ **过滤器事件优化**: 过滤器改变时也使用延迟刷新
+```csharp
+private void OnInfoFilterChanged(bool value)
+{
+ infoFilter = value;
+ needRefresh = true; // 而不是立即RefreshLogDisplay()
+}
+```
+
+#### SettingsModule.cs
+4. ✅ **移除ForceUpdateCanvases**: Canvas会自动在下一帧更新
+```csharp
+private void ApplyResolution(Vector2 resolution)
+{
+ mainWindow.sizeDelta = resolution;
+ currentResolutionText.text = $"当前窗口尺寸: {resolution.x} x {resolution.y}";
+
+ // 移除了 Canvas.ForceUpdateCanvases();
+ // Canvas会自动更新,不需要强制刷新
+}
+```
+
+### 2. 中文字体警告
+
+**问题描述**:
+```
+The character with Unicode value \u5F84 was not found in the [LiberationSans SDF]
+font asset or any potential fallbacks.
+```
+
+**原因**:
+- RuntimeUIGenerator使用的默认字体 `LiberationSans SDF` 不支持中文字符
+- TextMeshPro需要专门的中文字体资源
+
+**解决方案** (选择其一):
+
+#### 方案1: 使用中文字体 (推荐)
+```csharp
+// 在游戏初始化时设置中文字体
+UniversalDebugTool.Init();
+
+// 加载支持中文的TMP字体
+TMP_FontAsset chineseFont = Resources.Load("Fonts/ChineseFont SDF");
+UniversalDebugTool.SetSDFFont(chineseFont);
+```
+
+#### 方案2: 禁用字体警告
+在RuntimeUIGenerator的GetDefaultFont方法中添加过滤:
+```csharp
+private static TMP_FontAsset GetDefaultFont()
+{
+ // 禁用TMP字体警告
+ TMPro.TMP_Settings.warningsDisabled = true;
+
+ // 查找默认字体...
+}
+```
+
+#### 方案3: 创建中文字体资源
+1. 在Unity中:Window > TextMeshPro > Font Asset Creator
+2. 选择支持中文的字体(如Arial Unicode MS、Microsoft YaHei等)
+3. 设置Character Set为Unicode或Custom Characters
+4. 添加常用中文字符
+5. 生成字体资源并在代码中加载
+
+## 📋 修改总结
+
+### 文件变更
+
+#### ConsoleModule.cs
+- ✅ 添加 `needRefresh` 标志
+- ✅ 添加 `lastRefreshFrame` 帧计数
+- ✅ 修改 `OnLogMessageReceived` 使用延迟刷新
+- ✅ 修改 `Update` 方法处理延迟刷新和滚动
+- ✅ 修改所有过滤器事件使用延迟刷新
+
+#### SettingsModule.cs
+- ✅ 移除 `Canvas.ForceUpdateCanvases()` 调用
+
+### 性能影响
+
+✅ **更好**: 延迟刷新减少了不必要的UI重建
+✅ **更稳定**: 避免了rebuild loop错误
+✅ **无副作用**: 延迟一帧刷新对用户体验无影响
+
+## 🧪 测试建议
+
+### 1. 测试Rebuild Loop修复
+```csharp
+void Start()
+{
+ UniversalDebugTool.Init();
+
+ // 快速生成大量日志
+ for (int i = 0; i < 100; i++)
+ {
+ Debug.Log($"测试日志 {i}");
+ Debug.LogWarning($"警告 {i}");
+ Debug.LogError($"错误 {i}");
+ }
+
+ // 不应该再有rebuild loop错误
+}
+```
+
+### 2. 测试滚动功能
+```csharp
+void Update()
+{
+ if (Input.GetKeyDown(KeyCode.Space))
+ {
+ Debug.Log($"新日志 - 帧数: {Time.frameCount}");
+ // 应该自动滚动到底部(如果锁定滚动已启用)
+ }
+}
+```
+
+### 3. 测试过滤器
+1. 生成多种类型的日志
+2. 点击Console标签页
+3. 切换Info/Warning/Error/Fatal过滤器
+4. 不应该有rebuild loop错误
+
+### 4. 测试分辨率设置
+1. 进入Settings标签页
+2. 修改宽度和高度
+3. 点击"应用"按钮
+4. 不应该有rebuild loop错误
+
+## ⚠️ 注意事项
+
+### 关于中文字体
+如果你的游戏需要显示中文,必须:
+1. 创建或导入支持中文的TMP字体资源
+2. 在初始化后调用 `UniversalDebugTool.SetSDFFont(yourChineseFont)`
+3. 或者在RuntimeUIGenerator中修改GetDefaultFont方法返回中文字体
+
+### 最佳实践
+```csharp
+public class GameInit : MonoBehaviour
+{
+ [SerializeField] private TMP_FontAsset chineseFont;
+
+ void Start()
+ {
+ // 1. 初始化调试工具
+ UniversalDebugTool.Init();
+
+ // 2. 设置中文字体(如果需要)
+ if (chineseFont != null)
+ {
+ UniversalDebugTool.SetSDFFont(chineseFont);
+ }
+
+ // 3. 其他初始化...
+ }
+}
+```
+
+## ✅ 预期结果
+
+修复后,你应该看到:
+- ✅ 没有 "Trying to remove/add ... from/to rebuild list" 错误
+- ✅ Console正常显示日志
+- ✅ 过滤器正常工作
+- ✅ 滚动功能正常
+- ⚠️ 可能仍有字体警告(如果没有设置中文字体)
+
+字体警告不影响功能,只是文本显示为方块。如果需要中文显示,请按照上述方案添加中文字体。
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/BUGFIX_REBUILD_LOOP.md.meta b/Packages/com.bywaystudios.meowmentdebugtool/BUGFIX_REBUILD_LOOP.md.meta
new file mode 100644
index 0000000..a555966
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/BUGFIX_REBUILD_LOOP.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 3d6ac60c7ac1db84299fc8dde7508c38
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/CHANGELOG.md b/Packages/com.bywaystudios.meowmentdebugtool/CHANGELOG.md
index a69f5fb..c92480c 100644
--- a/Packages/com.bywaystudios.meowmentdebugtool/CHANGELOG.md
+++ b/Packages/com.bywaystudios.meowmentdebugtool/CHANGELOG.md
@@ -5,6 +5,50 @@
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
版本号遵循 [Semantic Versioning](https://semver.org/lang/zh-CN/)。
+## [0.3.0] - 2025-12-22
+
+### Added
+- **控制台模块 (Console)**
+ - 实时捕获并显示Unity日志(Info、Warning、Error、Fatal)
+ - 支持日志类型过滤(可单独开关各类型日志显示)
+ - 支持日志点击查看详细信息(堆栈跟踪)
+ - 日志数量统计和实时更新
+ - 支持清空日志功能
+ - 支持锁定滚动功能(自动滚动到最新日志)
+ - 日志项对象池优化,提升性能
+ - 最大日志数限制(默认100条,可配置)
+ - 日志详情区域显示完整堆栈信息
+ - 使用UGUI实现,支持ScrollRect滚动
+
+- **暂时隐藏功能**
+ - 工具栏新增"暂时隐藏(5秒)"按钮
+ - 用于截图时临时隐藏调试工具UI
+ - 自动在指定时间后恢复显示
+ - 支持防重入保护,避免重复触发
+ - 恢复后保持浮窗状态,不自动打开主窗口
+
+### Changed
+- 重构代码架构,将功能模块化
+ - 新增 `IDebugModule` 接口
+ - 拆分为独立模块:`ParametersModule`、`CustomButtonsModule`、`ToolbarModule`、`SettingsModule`、`ConsoleModule`
+- 优化控制台UI布局
+ - ControlPanel高度优化为40像素
+ - LogArea和DetailArea固定高度
+ - 移除不常用的Spacer元素
+- 优化日志显示
+ - 日志项高度从30增加到50像素
+ - 字体大小从22增加到28
+ - 添加上下边距提升可读性
+- 移除所有emoji字符,避免字体缺失警告
+- 锁定滚动功能默认开启
+
+### Fixed
+- 修复Canvas rebuild loop错误(延迟刷新机制)
+- 修复日志项RectTransform锚点设置问题
+- 修复VerticalLayoutGroup子元素高度控制问题
+- 修复页面未激活时不必要的更新操作
+- 修复暂时隐藏功能第二次执行失败的问题
+
## [0.2.2] - 2025-12-19
### Changed
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_INTEGRATION.md b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_INTEGRATION.md
new file mode 100644
index 0000000..8cd95d1
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_INTEGRATION.md
@@ -0,0 +1,236 @@
+# Console 控制台模块 - 添加说明
+
+## ✅ 已完成的工作
+
+### 1. 新增文件
+
+#### [LogNode.cs](Runtime/LogNode.cs)
+日志节点数据结构,包含:
+- LogType: 日志类型(Info/Warning/Error/Exception)
+- LogMessage: 日志消息
+- StackTrace: 堆栈跟踪
+- LogTime: 日志时间
+- LogFrameCount: 日志帧数
+
+#### [ConsoleModule.cs](Runtime/ConsoleModule.cs)
+控制台模块实现,基于UGUI,包含以下功能:
+- ✅ 实时捕获Unity日志
+- ✅ 日志分类和过滤(Info/Warning/Error/Fatal)
+- ✅ 锁定滚动到底部
+- ✅ 点击查看详细堆栈信息
+- ✅ 清除日志功能
+- ✅ 日志颜色区分
+- ✅ 对象池性能优化
+- ✅ 最大日志行数限制(500行)
+- ✅ SDF字体支持
+
+### 2. 修改的文件
+
+#### [UniversalDebugTool.cs](Runtime/UniversalDebugTool.cs)
+添加了以下内容:
+1. **序列化字段** - Console页面的所有UI组件引用
+2. **ConsoleModule实例** - 控制台模块对象
+3. **初始化代码** - 在InitializeDebugTool中创建和注册Console模块
+4. **Update方法** - 调用consoleModule.Update()更新UI
+5. **OnDestroy方法** - 清理控制台模块资源
+6. **SetSDFFont支持** - 为Console模块应用字体
+
+## 📋 需要在Unity中配置的UI
+
+### Unity Inspector 配置清单
+
+在UniversalDebugTool组件的Inspector中,需要配置以下字段:
+
+```
+[控制台页面]
+├── Console Page (GameObject)
+├── Console Log Scroll Rect (ScrollRect)
+├── Console Log Content (RectTransform)
+├── Console Detail Scroll Rect (ScrollRect)
+├── Console Detail Text (TMP_Text)
+├── Console Clear Button (Button)
+├── Console Lock Scroll Toggle (Toggle)
+├── Console Info Filter Toggle (Toggle)
+├── Console Warning Filter Toggle (Toggle)
+├── Console Error Filter Toggle (Toggle)
+├── Console Fatal Filter Toggle (Toggle)
+└── Console Log Item Prefab (GameObject)
+```
+
+### UI层次结构示例
+
+```
+ConsolePage
+├── ControlPanel (HorizontalLayoutGroup)
+│ ├── ClearButton
+│ ├── LockScrollToggle
+│ ├── Spacer (LayoutElement - FlexibleWidth)
+│ ├── InfoFilterToggle
+│ ├── WarningFilterToggle
+│ ├── ErrorFilterToggle
+│ └── FatalFilterToggle
+│
+├── LogArea (60% 高度)
+│ └── LogScrollView (ScrollRect)
+│ ├── Viewport
+│ └── Content (VerticalLayoutGroup)
+│ └── [日志项动态生成在这里]
+│
+└── DetailArea (40% 高度)
+ └── DetailScrollView (ScrollRect)
+ ├── Viewport
+ └── Content
+ └── DetailText
+```
+
+### 日志项预制件 (ConsoleLogItemPrefab)
+
+创建一个预制件,结构如下:
+```
+LogItem (GameObject)
+├── Toggle (Toggle组件)
+├── Background (Image)
+└── Label (TextMeshPro - Text)
+ - RichText: 启用
+ - Word Wrapping: 启用
+ - Overflow: Overflow
+```
+
+## 🎨 UI组件配置建议
+
+### ControlPanel
+- Component: HorizontalLayoutGroup
+- Padding: (10, 10, 10, 10)
+- Spacing: 10
+- Child Force Expand: Width = false, Height = false
+
+### LogScrollView
+- Component: ScrollRect
+- Content: 指向LogContent
+- Vertical: ✅
+- Horizontal: ❌
+- Movement Type: Elastic
+- Inertia: ✅
+- Scrollbar Visibility: Auto Hide
+
+### LogContent
+- Component: VerticalLayoutGroup
+- Child Alignment: Upper Center
+- Child Control Size: Height = ✅
+- Child Force Expand: Width = ✅
+- Spacing: 2
+
+### DetailScrollView
+- Component: ScrollRect
+- Vertical: ✅
+- Horizontal: ❌
+- Movement Type: Clamped
+
+### DetailText
+- Rich Text: ✅
+- Wrapping: ✅
+- Overflow: Overflow
+- Font Size: 14-16
+
+### Toggle组件
+- Is On: 根据默认值
+- Toggle Transition: Fade
+- 每个Toggle添加Label (TMP_Text)显示文本
+
+## 🔧 代码集成
+
+### 模块已自动集成
+ConsoleModule已经在UniversalDebugTool中自动初始化和管理,无需额外代码。
+
+### 使用示例
+
+```csharp
+// 1. 初始化调试工具(会自动初始化Console)
+UniversalDebugTool.Init();
+
+// 2. 设置字体(可选)
+UniversalDebugTool.SetSDFFont(myFont);
+
+// 3. 获取日志统计(可选)
+if (UniversalDebugTool.InstanceExists)
+{
+ var console = UniversalDebugTool.Instance.consoleModule;
+ if (console != null)
+ {
+ console.GetLogCount(out int info, out int warning,
+ out int error, out int fatal);
+ Debug.Log($"日志: Info={info}, Warn={warning}, " +
+ $"Error={error}, Fatal={fatal}");
+ }
+}
+```
+
+## 📊 与GameFramework对比
+
+### 主要差异
+
+| 项目 | GameFramework | MeowmentDebugTool |
+|------|---------------|-------------------|
+| UI系统 | OnGUI | UGUI |
+| 渲染方式 | 即时模式(每帧重绘) | 保留模式(按需刷新) |
+| 性能 | 中等 | 更优(对象池优化) |
+| 布局方式 | GUILayout | LayoutGroup + RectTransform |
+| 交互组件 | GUILayout.Button/Toggle | Button/Toggle组件 |
+| 滚动视图 | GUILayout.BeginScrollView | ScrollRect组件 |
+| 定制性 | 通过GUISkin | 完全UGUI定制 |
+
+### 实现等价性
+
+✅ **完全实现的功能**:
+- 日志捕获(Application.logMessageReceived)
+- 日志分类(Info/Warning/Error/Fatal)
+- 过滤器(4种日志类型独立过滤)
+- 锁定滚动
+- 选中查看详情
+- 清除日志
+- 日志颜色区分
+- 最大行数限制
+
+✅ **优化功能**:
+- 对象池(避免频繁创建销毁)
+- UGUI性能更好
+- 更灵活的布局系统
+
+❌ **未实现的功能**:
+- 复制到剪贴板(可以通过DetailText选择复制)
+- SettingComponent持久化(使用PlayerPrefs替代即可)
+
+## 🎯 后续步骤
+
+1. **在Unity中创建UI**
+ - 在Scene或Prefab中创建Console页面UI
+ - 按照层次结构创建各个组件
+ - 创建日志项预制件
+
+2. **配置引用**
+ - 在UniversalDebugTool组件Inspector中
+ - 将所有Console相关UI组件拖拽到对应字段
+
+3. **测试**
+ - 运行游戏
+ - 调用 `UniversalDebugTool.Init()`
+ - 查看Console标签页
+ - 测试各个过滤器和功能
+
+4. **调整样式**(可选)
+ - 修改颜色、字体大小
+ - 调整布局间距
+ - 优化日志项高度
+
+## ⚠️ 注意事项
+
+1. **日志项预制件必须有Toggle组件**
+2. **ScrollRect的Content必须正确设置**
+3. **VerticalLayoutGroup的设置影响滚动性能**
+4. **大量日志时注意性能(已有500行限制)**
+5. **确保Console Page在初始化时是隐藏的**
+
+## 📚 参考文档
+
+- [CONSOLE_MODULE_GUIDE.md](CONSOLE_MODULE_GUIDE.md) - 详细的UI结构和配置指南
+- [REFACTORING_NOTES.md](REFACTORING_NOTES.md) - 模块化重构说明
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_INTEGRATION.md.meta b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_INTEGRATION.md.meta
new file mode 100644
index 0000000..84de8e0
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_INTEGRATION.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 9bc4f10ea5e6a9d49b550c5aec275f1a
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_MODULE_GUIDE.md b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_MODULE_GUIDE.md
new file mode 100644
index 0000000..8cf5eca
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_MODULE_GUIDE.md
@@ -0,0 +1,171 @@
+# Console 控制台模块 UI 结构说明
+
+## 概述
+
+Console模块是一个基于UGUI的日志控制台,用于实时显示Unity的日志信息(Info/Warning/Error/Exception)。
+
+## 功能特性
+
+- ✅ 实时捕获Unity日志(Application.logMessageReceived)
+- ✅ 日志分类显示(Info/Warning/Error/Fatal)
+- ✅ 日志过滤器(可以单独开关各类型日志)
+- ✅ 锁定滚动到底部
+- ✅ 点击日志查看详细堆栈信息
+- ✅ 清除所有日志
+- ✅ 日志颜色区分
+- ✅ 最大日志行数限制(默认500行)
+- ✅ 对象池优化性能
+
+## UI结构
+
+### Console Page 层次结构
+```
+ConsolePage (GameObject)
+├── ControlPanel (水平布局)
+│ ├── ClearButton (Button) - 清空日志按钮
+│ ├── LockScrollToggle (Toggle) - 锁定滚动
+│ ├── Spacer (空白区域)
+│ ├── InfoFilterToggle (Toggle) - Info过滤器
+│ ├── WarningFilterToggle (Toggle) - Warning过滤器
+│ ├── ErrorFilterToggle (Toggle) - Error过滤器
+│ └── FatalFilterToggle (Toggle) - Fatal过滤器
+│
+├── LogScrollView (ScrollRect) - 日志列表区域
+│ └── LogContent (RectTransform) - 日志内容容器
+│ └── [动态生成的日志项]
+│
+└── DetailScrollView (ScrollRect) - 详细信息区域
+ └── DetailText (TMP_Text) - 显示选中日志的详细信息和堆栈
+```
+
+### 日志项预制件结构 (ConsoleLogItemPrefab)
+```
+LogItem (GameObject)
+├── Toggle (Toggle组件) - 用于选中日志
+├── Background (Image) - 背景
+└── Label (TMP_Text) - 显示日志文本
+```
+
+## 序列化字段配置
+
+在 UniversalDebugTool 的 Inspector 中需要配置以下字段:
+
+### Console页面字段
+```csharp
+[Header("控制台页面")]
+consolePage // 控制台页面根对象
+consoleLogScrollRect // 日志列表ScrollRect
+consoleLogContent // 日志内容容器RectTransform
+consoleDetailScrollRect // 详情ScrollRect
+consoleDetailText // 详情文本TMP_Text
+consoleClearButton // 清空按钮
+consoleLockScrollToggle // 锁定滚动Toggle
+consoleInfoFilterToggle // Info过滤Toggle
+consoleWarningFilterToggle // Warning过滤Toggle
+consoleErrorFilterToggle // Error过滤Toggle
+consoleFatalFilterToggle // Fatal过滤Toggle
+consoleLogItemPrefab // 日志项预制件
+```
+
+## UI组件要求
+
+### 1. ControlPanel
+- 使用 HorizontalLayoutGroup
+- 建议添加 ContentSizeFitter
+- Padding: 10, 10, 10, 10
+- Spacing: 10
+
+### 2. LogScrollView
+- ScrollRect 设置:
+ - Vertical: true
+ - Horizontal: false
+ - Movement Type: Elastic
+ - Scrollbar Visibility: Automatic If Needed
+- LogContent 需要 VerticalLayoutGroup:
+ - Child Alignment: Upper Center
+ - Child Force Expand: Width
+ - Child Control Size: Height
+ - Spacing: 2
+
+### 3. DetailScrollView
+- ScrollRect 设置:
+ - Vertical: true
+ - Horizontal: false
+ - Movement Type: Clamped
+- 建议高度: 150-200
+- DetailText 设置:
+ - Enable Word Wrapping
+ - Overflow: Overflow
+ - Enable Rich Text
+
+### 4. Toggles
+- 每个Toggle需要一个Label (TMP_Text)
+- 建议宽度: 100-120
+- Toggle Group: 不需要(可以多选)
+
+## 日志颜色配置
+
+在 ConsoleModule 中默认的颜色:
+```csharp
+Info: Color.white (255, 255, 255)
+Warning: Color.yellow (255, 255, 0)
+Error: Color.red (255, 0, 0)
+Fatal: Color(0.7f, 0.2f, 0.2f) (178, 51, 51)
+```
+
+## 性能优化
+
+1. **对象池机制**: 日志项使用对象池,避免频繁创建销毁
+2. **最大行数限制**: 默认500行,防止内存溢出
+3. **按需刷新**: 只在日志变化或过滤器改变时刷新显示
+4. **Toggle优化**: 使用Toggle而不是Button,减少重绘
+
+## 使用示例
+
+### 在代码中获取日志统计
+```csharp
+if (UniversalDebugTool.InstanceExists)
+{
+ var console = UniversalDebugTool.Instance.consoleModule;
+ if (console != null)
+ {
+ console.GetLogCount(out int info, out int warning, out int error, out int fatal);
+ Debug.Log($"日志统计 - Info:{info}, Warning:{warning}, Error:{error}, Fatal:{fatal}");
+ }
+}
+```
+
+### 设置字体
+```csharp
+UniversalDebugTool.SetSDFFont(myFont);
+// 会自动应用到控制台模块
+```
+
+## 注意事项
+
+1. **日志项预制件**: 必须包含 Toggle 和 TMP_Text 组件
+2. **ScrollRect**: 必须正确设置 Content 和 Viewport
+3. **性能**: 大量日志时建议增加日志项的高度以减少可见数量
+4. **线程安全**: 日志回调在主线程执行,无需担心线程问题
+5. **内存管理**: 超过最大行数的日志会自动删除
+
+## 与GameFramework的差异
+
+| 特性 | GameFramework (GUI) | MeowmentDebugTool (UGUI) |
+|------|---------------------|--------------------------|
+| UI系统 | OnGUI (即时模式) | UGUI (保留模式) |
+| 性能 | 每帧重绘 | 按需刷新 |
+| 布局 | GUILayout自动布局 | RectTransform + LayoutGroup |
+| 交互 | GUILayout.Button/Toggle | Button/Toggle组件 |
+| 对象池 | 不需要 | 使用对象池优化 |
+| 滚动 | GUILayout.BeginScrollView | ScrollRect组件 |
+
+## 未来扩展
+
+可以考虑添加的功能:
+- [ ] 搜索/过滤日志内容
+- [ ] 导出日志到文件
+- [ ] 日志标签/分类
+- [ ] 日志统计图表
+- [ ] 复制日志到剪贴板
+- [ ] 日志时间范围过滤
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_MODULE_GUIDE.md.meta b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_MODULE_GUIDE.md.meta
new file mode 100644
index 0000000..90d1a6f
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_MODULE_GUIDE.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 2e77813ce2d912b42b65134e2ce344f9
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_QUICK_SETUP.md b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_QUICK_SETUP.md
new file mode 100644
index 0000000..633fff1
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_QUICK_SETUP.md
@@ -0,0 +1,233 @@
+# Console模块快速设置指南
+
+## 🚀 5分钟快速设置
+
+### 步骤1: 创建Console页面GameObject
+
+在UniversalDebugTool的预制件中,创建以下结构:
+
+```
+[添加到ContentContainer下]
+└── ConsolePage
+ ├── ControlPanel
+ │ ├── ClearButton (Button)
+ │ ├── LockScrollToggle (Toggle + Label)
+ │ ├── Spacer (Empty GameObject + LayoutElement)
+ │ ├── InfoToggle (Toggle + Label)
+ │ ├── WarningToggle (Toggle + Label)
+ │ ├── ErrorToggle (Toggle + Label)
+ │ └── FatalToggle (Toggle + Label)
+ │
+ ├── LogArea
+ │ └── LogScrollView (ScrollRect)
+ │ └── Viewport
+ │ └── Content (VerticalLayoutGroup)
+ │
+ └── DetailArea
+ └── DetailScrollView (ScrollRect)
+ └── Viewport
+ └── Content
+ └── DetailText (TMP_Text)
+```
+
+### 步骤2: 配置组件
+
+#### ConsolePage
+- RectTransform: Stretch (全屏)
+- 默认禁用(Active = false)
+
+#### ControlPanel
+- Height: 50
+- Add Component: HorizontalLayoutGroup
+ - Padding: 10, 10, 10, 10
+ - Spacing: 10
+ - Child Force Expand: 都不勾选
+
+#### Spacer (占位符)
+- Add Component: LayoutElement
+ - Flexible Width: 1
+
+#### LogArea
+- Height: 60% (~400)
+- Add Component: VerticalLayoutGroup
+
+#### LogScrollView
+- Add Component: ScrollRect
+ - Content: LogContent
+ - Vertical: ✅
+ - Horizontal: ❌
+ - Scrollbar Visibility: Auto Hide And Expand Viewport
+
+#### LogContent
+- Add Component: VerticalLayoutGroup
+ - Child Alignment: Upper Center
+ - Spacing: 2
+ - Child Control Size: Height ✅
+ - Child Force Expand: Width ✅
+- Add Component: ContentSizeFitter
+ - Vertical Fit: Preferred Size
+
+#### DetailArea
+- Height: 40% (~200)
+
+#### DetailScrollView
+- 同LogScrollView配置
+
+#### DetailText
+- Font Size: 14
+- Color: White
+- Alignment: Top Left
+- Overflow: Overflow
+- Wrapping: Enabled
+- Rich Text: ✅
+
+### 步骤3: 创建日志项预制件
+
+创建一个新的预制件 `ConsoleLogItem`:
+
+```
+LogItem
+├── Toggle (Toggle组件)
+│ - Is On: false
+│ - Transition: None或Fade
+│
+├── Background (Image)
+│ - Color: (30, 30, 30, 255)
+│
+└── Label (TextMeshPro)
+ - Font Size: 12
+ - Color: White
+ - Alignment: Middle Left
+ - Overflow: Truncate
+ - Rich Text: ✅
+```
+
+组件设置:
+- RectTransform:
+ - Anchor: Stretch Horizontal
+ - Height: 25
+ - Left: 0, Right: 0
+- Toggle:
+ - Target Graphic: Background
+ - Graphic: Background
+
+### 步骤4: 配置UniversalDebugTool
+
+在Inspector中找到 `[控制台页面]` 部分,拖拽对应的对象:
+
+```
+✅ Console Page → ConsolePage
+✅ Console Log Scroll Rect → LogScrollView
+✅ Console Log Content → LogContent
+✅ Console Detail Scroll Rect → DetailScrollView
+✅ Console Detail Text → DetailText
+✅ Console Clear Button → ClearButton
+✅ Console Lock Scroll Toggle → LockScrollToggle
+✅ Console Info Filter Toggle → InfoToggle
+✅ Console Warning Filter Toggle → WarningToggle
+✅ Console Error Filter Toggle → ErrorToggle
+✅ Console Fatal Filter Toggle → FatalToggle
+✅ Console Log Item Prefab → ConsoleLogItem预制件
+```
+
+### 步骤5: 测试
+
+```csharp
+// 在游戏开始时调用
+UniversalDebugTool.Init();
+
+// 测试日志
+Debug.Log("这是一条Info日志");
+Debug.LogWarning("这是一条Warning日志");
+Debug.LogError("这是一条Error日志");
+```
+
+运行游戏,点击调试工具,切换到"控制台"标签页,应该能看到日志了!
+
+## 🎨 样式建议
+
+### 颜色方案(深色主题)
+```
+Background: (20, 20, 20)
+ControlPanel: (40, 40, 40)
+LogItem: (30, 30, 30)
+LogItem Selected: (60, 60, 60)
+Text: (220, 220, 220)
+
+日志颜色:
+Info: White (255, 255, 255)
+Warning: Yellow (255, 235, 0)
+Error: Red (255, 80, 80)
+Fatal: Dark Red (180, 50, 50)
+```
+
+### 字体大小
+```
+ControlPanel按钮: 14
+Toggle标签: 12
+日志项: 11-12
+详情文本: 13-14
+```
+
+### 间距
+```
+ControlPanel Spacing: 10
+LogContent Spacing: 2
+Padding: 10
+```
+
+## ⚡ 性能优化提示
+
+1. **限制可见日志项**: 调整LogArea高度,减少同时渲染的日志数量
+2. **日志项高度**: 25-30像素最佳,太高会影响滚动性能
+3. **最大日志数**: 默认500行,可在ConsoleModule构造函数中修改maxLine
+4. **禁用不需要的过滤器**: 减少日志显示可以提升性能
+
+## 🐛 常见问题
+
+### Q: 日志不显示?
+A: 检查:
+1. Console Page是否已添加到pages字典
+2. 是否调用了UniversalDebugTool.Init()
+3. 日志项预制件是否正确配置
+
+### Q: 滚动不工作?
+A: 检查:
+1. ScrollRect的Content是否正确设置
+2. Content是否有VerticalLayoutGroup
+3. Content Size Fitter是否启用
+
+### Q: 点击日志无反应?
+A: 检查:
+1. 日志项是否有Toggle组件
+2. Toggle的Target Graphic是否设置
+3. EventSystem是否存在于场景中
+
+### Q: 性能问题?
+A: 尝试:
+1. 减少maxLine值(默认500)
+2. 减少LogArea高度
+3. 使用Text而非TextMeshPro(性能更好但效果差)
+4. 关闭不需要的日志类型
+
+## 📱 移动端优化
+
+如果在移动设备上使用:
+
+1. 增大日志项高度(35-40像素)
+2. 增大字体(14-16)
+3. 减少最大日志数(200-300行)
+4. 使用简化的日志格式(去掉帧数显示)
+
+## ✨ 完成!
+
+现在你已经有一个功能完整的Console控制台了!
+
+测试所有功能:
+- ✅ 清除日志
+- ✅ 锁定/解锁滚动
+- ✅ 过滤不同类型日志
+- ✅ 点击查看详情
+- ✅ 滚动浏览日志
+
+享受调试吧! 🎉
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_QUICK_SETUP.md.meta b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_QUICK_SETUP.md.meta
new file mode 100644
index 0000000..365385b
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_QUICK_SETUP.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 1531af79f3e63374182c727d39576258
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_RUNTIME_READY.md b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_RUNTIME_READY.md
new file mode 100644
index 0000000..dd51251
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_RUNTIME_READY.md
@@ -0,0 +1,186 @@
+# Console模块 - 运行时UI创建完成
+
+## ✅ 已完成
+
+Console模块的UI已经添加到RuntimeUIGenerator中,会在运行时自动创建。
+
+## 🎯 使用方法
+
+### 1. 直接运行测试
+
+```csharp
+using UnityEngine;
+using MeowmentDebugTool;
+
+public class TestDebugTool : MonoBehaviour
+{
+ void Start()
+ {
+ // 初始化调试工具(会自动创建所有UI包括Console)
+ UniversalDebugTool.Init();
+
+ // 测试各种日志
+ Debug.Log("这是一条普通日志");
+ Debug.LogWarning("这是一条警告日志");
+ Debug.LogError("这是一条错误日志");
+
+ // 测试异常
+ try
+ {
+ throw new System.Exception("测试异常");
+ }
+ catch (System.Exception e)
+ {
+ Debug.LogException(e);
+ }
+ }
+
+ void Update()
+ {
+ // 按空格键生成测试日志
+ if (Input.GetKeyDown(KeyCode.Space))
+ {
+ Debug.Log($"测试日志 - 帧数: {Time.frameCount}");
+ }
+ }
+}
+```
+
+### 2. 运行游戏
+
+1. 创建一个空GameObject
+2. 添加TestDebugTool脚本
+3. 运行游戏
+4. Console页面会自动出现在标签页中
+
+### 3. 测试功能
+
+- ✅ **清空按钮**: 清除所有日志
+- ✅ **锁定滚动**: 自动滚动到最新日志
+- ✅ **过滤器**: 显示/隐藏不同类型的日志
+ - Info (白色)
+ - Warning (黄色)
+ - Error (红色)
+ - Fatal (深红色)
+- ✅ **点击日志**: 在下方显示详细信息和堆栈跟踪
+- ✅ **实时计数**: Toggle显示每种日志的数量
+
+## 📋 UI结构说明
+
+RuntimeUIGenerator会创建以下结构:
+
+```
+ConsolePage
+├── ControlPanel (控制面板 - 高度80)
+│ ├── ConsoleClearButton (清空按钮)
+│ ├── ConsoleLockScrollToggle (锁定滚动)
+│ ├── Spacer (弹性空白)
+│ ├── ConsoleInfoFilterToggle (Info过滤)
+│ ├── ConsoleWarningFilterToggle (Warning过滤)
+│ ├── ConsoleErrorFilterToggle (Error过滤)
+│ └── ConsoleFatalFilterToggle (Fatal过滤)
+│
+├── LogArea (60% 高度)
+│ └── ConsoleLogScrollView
+│ └── Viewport
+│ └── ConsoleLogContent (垂直布局组)
+│ └── [日志项动态生成]
+│
+└── DetailArea (40% 高度)
+ └── ConsoleDetailScrollView
+ └── Viewport
+ └── Content
+ └── ConsoleDetailText (详细信息)
+```
+
+## 🎨 样式配置
+
+### 颜色方案
+- **背景**: (12, 12, 12) - 深灰色
+- **日志区域**: (5, 5, 5) - 更深的灰色
+- **详情区域**: (8, 8, 8) - 中等深灰色
+- **日志项背景**: (12, 12, 12)
+- **日志项选中**: (25, 35, 45) - 蓝灰色
+
+### 日志颜色(ConsoleModule中定义)
+- **Info**: (255, 255, 255) - 白色
+- **Warning**: (255, 255, 0) - 黄色
+- **Error**: (255, 0, 0) - 红色
+- **Fatal**: (178, 51, 51) - 深红色
+
+### 字体大小
+- Toggle标签: 24
+- 日志项: 22
+- 详情文本: 24
+
+## 🔧 自定义配置
+
+如果需要修改样式,可以在RuntimeUIGenerator.cs中找到CreateConsolePage方法进行调整:
+
+### 修改日志项高度
+```csharp
+// 在CreateConsoleLogItemPrefab方法中
+rect.sizeDelta = new Vector2(0, 30); // 改为你想要的高度
+```
+
+### 修改区域比例
+```csharp
+// 在CreateConsolePage方法中
+logAreaLayout.flexibleHeight = 3; // 日志区域权重
+detailAreaLayout.flexibleHeight = 2; // 详情区域权重
+```
+
+### 修改最大日志数
+```csharp
+// 在ConsoleModule.cs构造函数中
+private int maxLine = 500; // 改为你想要的数量
+```
+
+## 🚀 性能提示
+
+1. **默认500行限制**: 超过的日志会自动删除
+2. **对象池优化**: 日志项会被重用,不会频繁创建销毁
+3. **按需刷新**: 只在日志变化或过滤器改变时刷新UI
+4. **适中的日志项高度**: 30像素平衡了可读性和性能
+
+## 📱 移动端建议
+
+如果在移动设备上运行:
+
+```csharp
+// 在CreateConsoleLogItemPrefab中调整
+labelTmp.fontSize = 28; // 增大字体
+rect.sizeDelta = new Vector2(0, 40); // 增加高度
+```
+
+## 🐛 调试技巧
+
+### 查看Console模块是否初始化成功
+```csharp
+if (UniversalDebugTool.InstanceExists)
+{
+ var console = UniversalDebugTool.Instance.GetType()
+ .GetField("consoleModule", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
+ ?.GetValue(UniversalDebugTool.Instance);
+
+ if (console != null)
+ {
+ Debug.Log("✅ Console模块已初始化");
+ }
+}
+```
+
+### 检查UI是否创建
+在Hierarchy中查找:
+- UniversalDebugTool_Canvas
+ - MainWindow
+ - ContentContainer
+ - ConsolePage ← 应该能找到这个
+
+## ✨ 完成!
+
+现在你可以直接运行游戏测试Console模块了!
+
+所有的UI都会在调用 `UniversalDebugTool.Init()` 时自动创建。
+
+享受调试吧! 🎉
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_RUNTIME_READY.md.meta b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_RUNTIME_READY.md.meta
new file mode 100644
index 0000000..0c0063e
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/CONSOLE_RUNTIME_READY.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: aa6bf6f6937d0ff4da7b444f776bf41e
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/README.md b/Packages/com.bywaystudios.meowmentdebugtool/README.md
index 571fd28..809741e 100644
--- a/Packages/com.bywaystudios.meowmentdebugtool/README.md
+++ b/Packages/com.bywaystudios.meowmentdebugtool/README.md
@@ -1,59 +1,129 @@
-# MeowMent Debug Tool(通用调试工具)
+# MeowMent Debug Tool(喵刻调试工具)
-一个面向运行时的 Unity 调试工具,内置多标签页调试面板、可拖拽悬浮按钮、设备/系统信息查看,以及通过特性自动生成的“自定义调试按钮”。
+一个强大的 Unity 运行时调试工具,提供多标签页调试面板、控制台日志、可拖拽悬浮按钮、系统信息查看以及自定义调试按钮等功能。
-核心脚本:
-
-- `Runtime/UniversalDebugTool.cs`
-- `Runtime/DraggableFloatingButton.cs`
-- `Editor/DebugToolPrefabGenerator.cs`
-- `Editor/CreateTabButtonPrefab.cs`
+**版本:** 0.3.0
+**适用平台:** 全平台(Windows、Android、iOS等)
+**Unity版本:** 2021.3 及以上
---
-## 功能概览
+## 📋 目录
-- 多标签页调试面板(默认分辨率 1080x2340):
- - 参数:设备信息、系统信息,一键复制到剪贴板。
- - 自定义按钮:通过特性自动收集项目中的调试方法并生成按钮。
- - 工具栏:简单的“时间调整”示例入口,可按项目需要扩展。
- - 设置:运行时修改调试窗口尺寸、重置为默认分辨率。
-- 悬浮调试按钮:
- - 关闭主窗口后,会显示一个可拖拽、自动吸附边缘的浮动按钮。
- - 点击可再次打开调试主窗口,拖动不会误触打开(内部做了拖拽判定)。
-- 运行时公共 API:
- - `UniversalDebugTool.Show() / Hide() / Toggle()` 控制显示。
- - `UniversalDebugTool.ShowInputDialog(...)` 弹出输入对话框。
- - `UniversalDebugTool.Instance.ReloadCustomButtons()` 重新扫描并生成自定义按钮。
+- [功能特性](#功能特性)
+- [给策划使用 - 基础功能](#给策划使用---基础功能)
+- [给客户端使用 - 初始化配置](#给客户端使用---初始化配置)
+- [给后端使用 - 添加自定义按钮](#给后端使用---添加自定义按钮)
+- [常见问题](#常见问题)
---
-## 安装
+## 🎯 功能特性
-### 方式一:本地拷贝(推荐在开发环境使用)
+### 核心功能模块
+- **参数查看**:实时查看设备信息、系统信息,支持一键复制
+- **自定义按钮**:通过特性自动生成调试按钮,无需手动添加
+- **工具栏**:时间调整工具、截图隐藏功能
+- **控制台**:实时捕获Unity日志,支持过滤、搜索、查看堆栈
+- **设置**:运行时修改分辨率
-1. 将 `com.bywaystudios.meowmentdebugtool@0.1.4` 整个文件夹放到你项目的 `Packages/` 目录下。
-2. 打开 Unity,等待重新导入即可在菜单中看到调试工具相关项。
-
-### 方式二:通过自建 Git / 私有仓库
-
-如果你已经把此包发布到自己的 Git 仓库或私有 Package Registry,可参考 Unity 官方文档,通过修改 `Packages/manifest.json` 的 `dependencies` / `scopedRegistries` 来添加:
-
-```jsonc
-"dependencies": {
- "com.bywaystudios.meowmentdebugtool": "0.1.4"
-}
-```
-
-> 具体部署方式视团队实际环境而定,这里不展开。
+### UI特性
+- 可拖拽悬浮按钮,自动吸附边缘
+- 多标签页设计,清晰分类
+- Canvas层级30000,始终在最上层
+- 支持自定义TextMeshPro字体
---
-## 快速开始
+## 👥 给策划使用 - 基础功能
-### 1. 在代码中初始化调试工具
+### 1. 如何打开调试工具
-调试工具现在支持**运行时自动生成UI**,无需手动创建预制体。只需在代码中调用:
+游戏运行后,屏幕左侧会显示一个**蓝色圆形浮窗按钮**:
+
+- **点击浮窗** → 打开调试主窗口
+- **拖动浮窗** → 改变位置(会自动吸附到屏幕边缘)
+- **点击左上角X** → 关闭主窗口,回到浮窗状态
+
+### 2. 功能页面说明
+
+调试窗口包含5个标签页:
+
+#### 📊 参数查看
+- **设备信息**:设备型号、系统版本、处理器、内存等
+- **系统信息**:Unity版本、图形API、显卡信息等
+- **复制按钮**:点击可复制信息到剪贴板,方便粘贴到bug报告
+
+#### 🎮 自定义按钮
+- 显示后端程序员添加的调试功能按钮
+- 点击按钮即可执行对应功能(如清理存档、添加道具等)
+- 不同按钮有不同颜色,方便区分
+
+**常见按钮示例:**
+- "清空玩家数据" - 重置游戏进度
+- "添加金币" - 增加游戏货币
+- "解锁所有关卡" - 开启所有内容
+- "重置今日任务" - 刷新每日任务
+
+#### 🛠️ 工具栏
+- **时间调整**:模拟时间流逝(用于测试时间相关功能)
+- **暂时隐藏(5秒)**:截图前点击此按钮,调试工具会隐藏5秒,方便截取干净的游戏画面
+
+**使用场景:**
+1. 需要截图游戏画面时
+2. 点击"暂时隐藏(5秒)"
+3. 调试工具消失,快速截图
+4. 5秒后自动恢复,继续调试
+
+#### 📝 控制台
+实时显示游戏日志,帮助定位问题:
+
+- **Info(白色)**:普通信息日志
+- **Warning(黄色)**:警告信息
+- **Error(红色)**:错误信息
+- **Fatal(深红)**:严重错误/异常
+
+**功能按钮:**
+- **清空**:清除所有日志
+- **锁定滚动**:勾选后自动滚动到最新日志
+- **过滤器**:点击Info/Warning/Error切换显示对应类型日志
+
+**查看详情:**
+- 点击任意日志条目 → 下方显示完整堆栈信息
+- 方便向程序员反馈详细错误
+
+#### ⚙️ 设置
+- **分辨率调整**:修改游戏窗口大小(仅编辑器/Windows有效)
+- **当前分辨率显示**:显示当前屏幕分辨率
+
+### 3. 日常测试工作流
+
+**测试新功能:**
+1. 打开调试工具
+2. 切换到"自定义按钮"页面
+3. 点击相关测试按钮(如"开启活动")
+4. 观察游戏效果
+5. 如有问题,切换到"控制台"查看错误
+
+**截图报bug:**
+1. 复现问题
+2. 点击"工具栏" → "暂时隐藏(5秒)"
+3. 截取游戏画面
+4. 切换回"控制台"截取错误日志
+5. 一起提交给程序
+
+**收集设备信息:**
+1. 切换到"参数查看"
+2. 点击"复制设备信息"或"复制系统信息"
+3. 粘贴到bug报告中
+
+---
+
+## 💻 给客户端使用 - 初始化配置
+
+### 1. 基础初始化
+
+在游戏启动时(通常在启动场景的初始化脚本中)调用:
```csharp
using UnityEngine;
@@ -62,14 +132,14 @@ using TMPro;
public class GameInitializer : MonoBehaviour
{
- public TMP_FontAsset customFont; // 可选:自定义字体
+ [SerializeField] private TMP_FontAsset customFont; // 拖入自定义字体
void Start()
{
- // 初始化调试工具(自动创建UI)
+ // 初始化调试工具
UniversalDebugTool.Init();
- // 可选:设置自定义SDF字体
+ // 设置自定义字体(可选)
if (customFont != null)
{
UniversalDebugTool.SetSDFFont(customFont);
@@ -78,27 +148,34 @@ public class GameInitializer : MonoBehaviour
}
```
-**初始化说明:**
+### 2. API说明
-- `UniversalDebugTool.Init()` 会自动创建完整的UI系统,包括:
- - 独立的 Canvas(排序顺序 30000,保证在最上层渲染)
- - 主调试窗口(含标签页、参数页、自定义按钮页、工具栏页、设置页)
- - 可拖拽的调试悬浮按钮
- - EventSystem(如果场景中没有)
-- `UniversalDebugTool.SetSDFFont()` 可以为所有UI文本设置自定义字体(可选)
+#### `UniversalDebugTool.Init()`
+初始化调试工具,自动创建:
+- Canvas(排序顺序30000)
+- 主调试窗口
+- 悬浮按钮
+- EventSystem(如果没有)
-### 2. 运行时使用
+**注意:**
+- 只需调用一次
+- 工具会自动DontDestroyOnLoad,场景切换不销毁
+- 未调用Init()前不显示任何UI
-进入 Play 模式后:
+#### `UniversalDebugTool.SetSDFFont(TMP_FontAsset fontAsset)`
+设置所有UI文本的字体:
+- 包括已创建的UI和后续创建的按钮
+- 支持中文、特殊字符
+- 建议使用支持中文的SDF字体
-- 默认显示主调试窗口在左上角
-- 点击左上角的 **X** 按钮,会隐藏主窗口并显示悬浮按钮
-- 拖动悬浮按钮改变位置(自动吸附边缘)
-- 点击悬浮按钮可重新打开主窗口(拖动不会误触)
+**字体推荐:**
+- 思源黑体 SDF
+- 阿里巴巴普惠体 SDF
+- 或项目现有的中文字体
### 3. 条件编译(推荐)
-为了确保在移除包后不影响主工程,建议使用条件编译:
+为了确保打包时不包含调试代码:
```csharp
void Start()
@@ -110,166 +187,361 @@ void Start()
}
```
-`MEOWMENT_DEBUG_TOOL` 宏会在包安装时自动定义,卸载时自动移除。
+**说明:**
+- `MEOWMENT_DEBUG_TOOL` 宏在包安装时自动定义
+- 移除包时自动移除,不影响项目编译
+- 正式包不会包含调试工具代码
----
-
-## 自定义调试按钮
-
-调试工具会在运行时通过反射扫描所有程序集,查找带有 `DebugButtonAttribute` 特性的方法,并在“自定义按钮”标签页中为其自动生成一个按钮。
-
-### 编写一个自定义调试方法
-
-> 要求:
-> - 方法必须是 `static`。
-> - 当前实现假定为**无参数**方法。如果需要参数,可结合 `ShowInputDialog` 自行封装。
-
-示例:
+### 4. 完整示例
```csharp
using UnityEngine;
+using MeowmentDebugTool;
+using TMPro;
-public static class DemoDebugActions
+public class Test : MonoBehaviour
{
- // 在“自定义按钮”页中会生成一个名为“打印金币数量”的按钮
- [DebugButton("打印金币数量", 0.3f, 0.6f, 1f)]
- private static void PrintCoinCount()
+ public TMP_FontAsset fontAsset;
+
+ void Start()
{
- Debug.Log($"Coins: {PlayerData.Coin}");
- }
-
- // 不传 displayName 时,按钮文字默认使用方法名
- [DebugButton]
- private static void KillAllEnemies()
- {
- EnemyManager.KillAll();
+ #if MEOWMENT_DEBUG_TOOL
+ // 初始化调试工具
+ UniversalDebugTool.Init();
+
+ // 设置字体
+ if (fontAsset != null)
+ {
+ UniversalDebugTool.SetSDFFont(fontAsset);
+ }
+ #endif
}
}
```
-`DebugButtonAttribute` 构造函数签名:
-
-```csharp
-public DebugButtonAttribute(string displayName = "", float r = 0.8f, float g = 0.8f, float b = 0.8f);
-```
-
-- `displayName`:按钮显示文字(可为空,为空则使用方法名)。
-- `r g b`:按钮背景色的 RGB 分量(0~1)。
-
-写好方法后:
-
-1. 进入 Play 模式。
-2. 打开调试工具 → 切换到“自定义按钮”标签页。
-3. 即可看到刚才添加的调试按钮,点击执行对应逻辑。
-
-如果你在运行时新增/修改了带有 `DebugButtonAttribute` 的方法(如通过热更等方式),可以调用:
-
-```csharp
-UniversalDebugTool.Instance.ReloadCustomButtons();
-```
-
-来重新扫描并刷新按钮列表。
-
---
-## 输入对话框(可选)
+## 🔧 给后端使用 - 添加自定义按钮
-调试工具内置了一个简单的输入对话框,可与自定义按钮组合使用:
+### 1. 基础用法
+
+使用 `[DebugButton]` 特性标记静态方法,调试工具会自动生成按钮:
+
+```csharp
+using UnityEngine;
+
+public static class PlayerDebugFunctions
+{
+ [DebugButton("清空玩家数据")]
+ private static void ClearPlayerData()
+ {
+ PlayerPrefs.DeleteAll();
+ Debug.Log("玩家数据已清空");
+ }
+
+ [DebugButton("添加1000金币")]
+ private static void AddCoins()
+ {
+ PlayerData.Coins += 1000;
+ Debug.Log($"当前金币:{PlayerData.Coins}");
+ }
+}
+```
+
+**运行效果:**
+- 在"自定义按钮"页面会出现两个按钮
+- 点击按钮执行对应方法
+
+### 2. 特性参数详解
+
+```csharp
+[DebugButton(string displayName = "", float r = 0.8f, float g = 0.8f, float b = 0.8f)]
+```
+
+#### 参数说明:
+- **displayName**:按钮显示文字(不填则使用方法名)
+- **r, g, b**:按钮背景颜色(RGB值,范围0-1)
+
+#### 示例:不同颜色按钮
+
+```csharp
+public static class GameDebugFunctions
+{
+ // 绿色按钮 - 安全操作
+ [DebugButton("保存游戏", 0.2f, 0.6f, 0.2f)]
+ private static void SaveGame()
+ {
+ GameManager.Save();
+ }
+
+ // 红色按钮 - 危险操作
+ [DebugButton("删除存档", 0.9f, 0.2f, 0.2f)]
+ private static void DeleteSave()
+ {
+ GameManager.DeleteSave();
+ }
+
+ // 蓝色按钮 - 功能测试
+ [DebugButton("跳到第10关", 0.2f, 0.5f, 0.9f)]
+ private static void JumpToLevel10()
+ {
+ LevelManager.LoadLevel(10);
+ }
+
+ // 默认颜色(灰色)
+ [DebugButton("打印游戏状态")]
+ private static void PrintGameState()
+ {
+ Debug.Log($"Level: {GameManager.CurrentLevel}");
+ }
+}
+```
+
+### 3. 使用输入对话框
+
+需要用户输入参数时,使用 `ShowInputDialog`:
```csharp
using TMPro;
-public static class DemoInputDebug
+public static class AdvancedDebugFunctions
{
[DebugButton("设置玩家等级")]
private static void SetPlayerLevel()
{
UniversalDebugTool.ShowInputDialog(
- "输入玩家等级",
+ "输入等级",
onConfirmAction: text =>
{
- if (int.TryParse(text, out var level))
+ if (int.TryParse(text, out int level))
{
PlayerData.Level = level;
- Debug.Log($"设置玩家等级为: {level}");
+ Debug.Log($"等级已设置为:{level}");
}
else
{
- Debug.LogWarning($"无效等级: {text}");
+ Debug.LogWarning("请输入有效数字");
}
},
initialValue: "1",
contentType: TMP_InputField.ContentType.IntegerNumber
);
}
-}
-```
-
-调用后会弹出一个输入框,用户点击确认时会把输入字符串传回回调函数中。
-
----
-
-## 公共 API 一览
-
-以下方法均定义在 `UniversalDebugTool` 中:
-
-**初始化和配置:**
-- `static void Init()`:初始化调试工具,自动创建完整的UI系统(包括Canvas、主窗口、悬浮按钮、EventSystem等)。
-- `static void SetSDFFont(TMP_FontAsset fontAsset)`:为所有UI文本设置自定义SDF字体,包括预制件模板和后续创建的按钮。
-
-**显示控制:**
-- `static bool InstanceExists`:当前场景中是否存在实例。
-- `static UniversalDebugTool Instance`:单例实例。
-- `static void Show()`:显示调试工具 GameObject。
-- `static void Hide()`:隐藏调试工具 GameObject。
-- `static void Toggle()`:在"窗口显示"和"窗口关闭 + 显示悬浮按钮"之间切换。
-
-**自定义按钮:**
-- `void ReloadCustomButtons()`:重新扫描并生成自定义按钮。
-
-**输入对话框:**
-- `static void ShowInputDialog(string title, Action onConfirmAction, string initialValue = "", TMP_InputField.ContentType contentType = TMP_InputField.ContentType.Standard)`:显示输入对话框。
-- `static void CloseInputDialog()`:关闭输入对话框并清理回调。
-
-**信息查看:**
-- `void CopyDeviceInfoToClipboard()` / `void CopySystemInfoToClipboard()`:复制对应信息到系统剪贴板。
-
-你也可以在自己项目的 UI / 快捷键逻辑中调用这些方法,例如:
-
-```csharp
-// 示例:按 F1 切换调试面板
-void Update()
-{
- if (Input.GetKeyDown(KeyCode.F1))
+
+ [DebugButton("设置玩家名称")]
+ private static void SetPlayerName()
{
- UniversalDebugTool.Toggle();
+ UniversalDebugTool.ShowInputDialog(
+ "输入名称",
+ onConfirmAction: name =>
+ {
+ PlayerData.Name = name;
+ Debug.Log($"名称已设置为:{name}");
+ },
+ initialValue: PlayerData.Name,
+ contentType: TMP_InputField.ContentType.Standard
+ );
}
}
```
+### 4. 条件编译(推荐)
+
+为了确保正式版不包含调试代码:
+
+```csharp
+public static class ItemDebugFunctions
+{
+ #if MEOWMENT_DEBUG_TOOL
+ [DebugButton("添加道具")]
+ private static void AddItem()
+ {
+ ItemManager.AddItem(1001, 10);
+ }
+ #endif
+}
+```
+
+### 5. 高级技巧
+
+#### 技巧1:分类管理
+按功能模块创建不同的类:
+
+```csharp
+// 玩家相关
+public static class PlayerDebug { ... }
+
+// 关卡相关
+public static class LevelDebug { ... }
+
+// 道具相关
+public static class ItemDebug { ... }
+```
+
+#### 技巧2:快速测试流程
+
+```csharp
+[DebugButton("快速进入战斗")]
+private static void QuickEnterBattle()
+{
+ // 1. 设置测试数据
+ PlayerData.Level = 10;
+ PlayerData.Coins = 9999;
+
+ // 2. 解锁功能
+ FeatureManager.UnlockAll();
+
+ // 3. 跳转场景
+ SceneManager.LoadScene("Battle");
+}
+```
+
+#### 技巧3:开发辅助
+
+```csharp
+[DebugButton("开启所有调试选项")]
+private static void EnableAllDebug()
+{
+ GameConfig.ShowFPS = true;
+ GameConfig.GodMode = true;
+ GameConfig.UnlimitedEnergy = true;
+ Debug.Log("所有调试选项已开启");
+}
+```
+
+### 6. 实战示例
+
+```csharp
+using UnityEngine;
+using UnityEngine.SceneManagement;
+using TMPro;
+
+public static class SampleDebugFunctions
+{
+ #region 玩家数据
+ [DebugButton("重置游戏", 0.9f, 0.3f, 0.3f)]
+ private static void ResetGame()
+ {
+ PlayerPrefs.DeleteAll();
+ SceneManager.LoadScene(0);
+ Debug.Log("游戏已重置");
+ }
+
+ [DebugButton("满级满资源", 0.2f, 0.8f, 0.2f)]
+ private static void MaxEverything()
+ {
+ PlayerData.Level = 99;
+ PlayerData.Coins = 999999;
+ PlayerData.Gems = 99999;
+ Debug.Log("已设置为满级满资源");
+ }
+ #endregion
+
+ #region 关卡测试
+ [DebugButton("跳关", 0.3f, 0.6f, 0.9f)]
+ private static void JumpToLevel()
+ {
+ UniversalDebugTool.ShowInputDialog(
+ "输入关卡号",
+ text =>
+ {
+ if (int.TryParse(text, out int level))
+ {
+ LevelManager.LoadLevel(level);
+ }
+ },
+ "1",
+ TMP_InputField.ContentType.IntegerNumber
+ );
+ }
+
+ [DebugButton("解锁所有关卡", 0.2f, 0.8f, 0.8f)]
+ private static void UnlockAllLevels()
+ {
+ for (int i = 0; i < 100; i++)
+ {
+ LevelManager.UnlockLevel(i);
+ }
+ Debug.Log("已解锁所有关卡");
+ }
+ #endregion
+
+ #region 系统测试
+ [DebugButton("清理未使用资源", 0.9f, 0.5f, 0.3f)]
+ private static void UnloadUnusedAssets()
+ {
+ Resources.UnloadUnusedAssets();
+ Debug.Log("已清理未使用的资源");
+ }
+
+ [DebugButton("触发GC")]
+ private static void ForceGC()
+ {
+ System.GC.Collect();
+ Debug.Log("已触发垃圾回收");
+ }
+ #endregion
+}
+```
+
---
-## 注意事项
+## ❓ 常见问题
-**依赖:**
-- Unity 新 UI(`UnityEngine.UI`)
-- TextMesh Pro(`TMPro`)
-- 包会自动创建 EventSystem(如果场景中没有)
+### Q1: 字体显示方块/乱码怎么办?
+**A:** 调用 `UniversalDebugTool.SetSDFFont()` 设置支持中文的SDF字体。
-**使用建议:**
-- 默认 UI 参考分辨率为 1080×2340,适合手机竖屏调试。可在"设置"页中修改窗口大小以适配不同设备。
-- 主窗口锚点在左上角,不受分辨率变化影响。
-- 悬浮按钮可在全屏范围内拖动,会自动吸附到边缘。
-- 工具栏中的"时间调整"逻辑仅是示例,需要在 `AdjustGameTime` 中实现实际的时间修改逻辑。
+### Q2: 自定义按钮不显示?
+**A:** 检查:
+- 方法是否为 `static`
+- 是否添加了 `[DebugButton]` 特性
+- 是否在 `#if MEOWMENT_DEBUG_TOOL` 内
-**字体设置:**
-- 所有 UI 文本默认使用 TMP 的默认字体。
-- 调用 `SetSDFFont()` 可以为所有文本(包括后续创建的自定义按钮)设置自定义字体。
+### Q3: 第二次点击"暂时隐藏"无效?
+**A:** 等待上一次隐藏结束,或查看控制台是否有"已经在隐藏状态中"的警告。
-**条件编译:**
-- 建议使用 `#if MEOWMENT_DEBUG_TOOL` 包裹调试工具相关代码。
-- 包安装时会自动定义 `MEOWMENT_DEBUG_TOOL` 宏,卸载时自动移除。
-- 这样可以确保移除包后不影响主工程编译。
+### Q4: 如何在正式版移除调试工具?
+**A:** 删除Packages目录下的工具包文件夹即可,`#if MEOWMENT_DEBUG_TOOL` 包裹的代码会自动失效。
-**进一步定制:**
-如需修改 UI 布局、颜色、标签页等,可以直接修改 `RuntimeUIGenerator.cs` 中的 UI 生成逻辑。
+### Q5: 控制台日志太多怎么办?
+**A:**
+- 点击"清空"按钮清除日志
+- 使用过滤器只显示Error/Warning
+- 工具默认只保留最新100条日志
+
+### Q6: 可以在多个场景使用吗?
+**A:** 可以,工具使用DontDestroyOnLoad,场景切换不会销毁。
+
+---
+
+## 📝 更新日志
+
+### [0.3.0] - 2025-12-22
+- ✨ 新增控制台模块,实时显示Unity日志
+- ✨ 新增暂时隐藏功能,方便截图
+- 🔨 重构代码架构,模块化设计
+- 🐛 修复多个UI布局问题
+
+### [0.2.2] - 2025-12-19
+- 🔨 默认显示浮窗而非主窗口
+- 🐛 优化初始化逻辑
+
+详见 [CHANGELOG.md](CHANGELOG.md)
+
+---
+
+## 📦 依赖
+
+- Unity 2021.3+
+- TextMesh Pro (com.unity.textmeshpro)
+- Unity UI (com.unity.ugui)
+
+---
+
+## 📧 联系方式
+
+如有问题或建议,请联系开发团队。
+
+---
+
+**祝调试顺利!** 🐱
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/REFACTORING_NOTES.md b/Packages/com.bywaystudios.meowmentdebugtool/REFACTORING_NOTES.md
new file mode 100644
index 0000000..9a4747a
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/REFACTORING_NOTES.md
@@ -0,0 +1,111 @@
+# MeowmentDebugTool 模块化重构说明
+
+## 重构概述
+
+已将 UniversalDebugTool 的4个主要功能模块分离成独立的脚本文件,使代码结构更清晰、更易维护。
+
+## 新增文件
+
+### 1. IDebugModule.cs
+- **作用**: 调试模块的基础接口
+- **方法**:
+ - `Initialize()`: 初始化模块
+ - `GetPage()`: 获取模块的UI页面GameObject
+ - `GetModuleName()`: 获取模块名称
+
+### 2. ParametersModule.cs
+- **作用**: 参数查看模块,显示设备和系统信息
+- **主要功能**:
+ - 显示设备信息(设备名称、型号、处理器等)
+ - 显示系统信息(Unity版本、平台、分辨率、图形设备等)
+ - 复制信息到剪贴板
+ - 刷新信息
+
+### 3. CustomButtonsModule.cs
+- **作用**: 自定义按钮模块,通过反射加载标记为DebugButton的方法
+- **主要功能**:
+ - 自动扫描并加载所有带 `[DebugButton]` 特性的静态方法
+ - 动态创建按钮UI
+ - 设置SDF字体
+ - 支持自定义按钮回调
+ - 点击按钮后自动关闭调试窗口
+
+### 4. ToolbarModule.cs
+- **作用**: 工具栏模块,提供时间调整等工具
+- **主要功能**:
+ - 时间调整滑块(支持秒和分钟显示)
+ - 增加/减少时间按钮
+ - 可扩展的游戏时间调整接口
+
+### 5. SettingsModule.cs
+- **作用**: 设置模块,提供分辨率设置等功能
+- **主要功能**:
+ - 自定义窗口分辨率
+ - 重置为默认分辨率
+ - 实时显示当前窗口尺寸
+
+## UniversalDebugTool.cs 的改动
+
+### 主要变化
+
+1. **移除了具体实现代码**:
+ - 参数查看功能 → ParametersModule
+ - 自定义按钮功能 → CustomButtonsModule
+ - 工具栏功能 → ToolbarModule
+ - 分辨率设置功能 → SettingsModule
+
+2. **新增模块管理**:
+ ```csharp
+ private ParametersModule parametersModule;
+ private CustomButtonsModule customButtonsModule;
+ private ToolbarModule toolbarModule;
+ private SettingsModule settingsModule;
+ private List allModules = new List();
+ ```
+
+3. **初始化流程**:
+ - `InitializeDebugTool()`: 创建所有模块实例并注册页面
+ - `InitializeAllModules()`: 调用各模块的Initialize方法
+
+4. **保留的公共API**:
+ - `CopyDeviceInfoToClipboard()` - 委托给 ParametersModule
+ - `CopySystemInfoToClipboard()` - 委托给 ParametersModule
+ - `RefreshAllInfo()` - 委托给 ParametersModule
+ - `SetCustomButtonCallback()` - 委托给 CustomButtonsModule
+ - `ReloadCustomButtons()` - 委托给 CustomButtonsModule
+
+## 优势
+
+1. **职责分离**: 每个模块只负责一个功能领域
+2. **易于维护**: 修改某个功能时只需要编辑对应的模块文件
+3. **可扩展性**: 添加新模块只需实现 IDebugModule 接口
+4. **代码清晰**: UniversalDebugTool.cs 现在主要负责协调各模块,代码更简洁
+
+## 使用方式
+
+使用方式完全不变,所有现有的API和功能保持兼容:
+
+```csharp
+// 初始化调试工具
+UniversalDebugTool.Init();
+
+// 设置字体
+UniversalDebugTool.SetSDFFont(myFont);
+
+// 刷新信息
+UniversalDebugTool.Instance.RefreshAllInfo();
+
+// 自定义按钮仍然使用相同的特性
+[DebugButton("测试按钮")]
+public static void TestMethod()
+{
+ Debug.Log("测试");
+}
+```
+
+## 未来扩展
+
+如果需要添加新的调试功能模块,只需:
+1. 创建新的类并实现 `IDebugModule` 接口
+2. 在 `UniversalDebugTool.InitializeDebugTool()` 中实例化并添加到 `allModules` 列表
+3. 调用 `InitializeAllModules()` 会自动初始化新模块
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/REFACTORING_NOTES.md.meta b/Packages/com.bywaystudios.meowmentdebugtool/REFACTORING_NOTES.md.meta
new file mode 100644
index 0000000..0b6f1dd
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/REFACTORING_NOTES.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 7a75e76e7a8253b4a97f7c353af12a0f
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/Runtime/ConsoleModule.cs b/Packages/com.bywaystudios.meowmentdebugtool/Runtime/ConsoleModule.cs
new file mode 100644
index 0000000..2a6204d
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/Runtime/ConsoleModule.cs
@@ -0,0 +1,579 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using TMPro;
+
+namespace MeowmentDebugTool
+{
+ ///
+ /// 控制台模块 - 显示Unity日志(基于UGUI实现)
+ ///
+ public class ConsoleModule : IDebugModule
+ {
+ #region 字段
+ private GameObject consolePage;
+
+ // UI组件
+ private ScrollRect logScrollRect;
+ private RectTransform logContent;
+ private ScrollRect detailScrollRect;
+ private TMP_Text detailText;
+
+ // 按钮
+ private Button clearButton;
+ private Toggle lockScrollToggle;
+ private Toggle infoFilterToggle;
+ private Toggle warningFilterToggle;
+ private Toggle errorFilterToggle;
+ private Toggle fatalFilterToggle;
+
+ // 日志项预制件
+ private GameObject logItemPrefab;
+
+ // 日志数据
+ private Queue logNodes = new Queue();
+ private LogNode selectedNode = null;
+
+ // 日志计数
+ private int infoCount = 0;
+ private int warningCount = 0;
+ private int errorCount = 0;
+ private int fatalCount = 0;
+
+ // 设置
+ private bool lockScroll = true;
+ private int maxLine = 200;
+ private bool infoFilter = true;
+ private bool warningFilter = true;
+ private bool errorFilter = true;
+ private bool fatalFilter = true;
+
+ // 颜色设置
+ private Color32 infoColor = Color.white;
+ private Color32 warningColor = Color.yellow;
+ private Color32 errorColor = Color.red;
+ private Color32 fatalColor = new Color(0.7f, 0.2f, 0.2f);
+
+ // UI对象池
+ private List logItemPool = new List();
+ private List activeLogItems = new List();
+
+ // 保存的字体
+ private TMP_FontAsset savedFontAsset = null;
+
+ // 延迟刷新标记
+ private bool needRefresh = false;
+ private int lastRefreshFrame = -1;
+ #endregion
+
+ #region 构造函数
+ public ConsoleModule(GameObject page, ScrollRect logScroll, RectTransform logContentTransform,
+ ScrollRect detailScroll, TMP_Text detail,
+ Button clearBtn, Toggle lockToggle, Toggle infoToggle, Toggle warningToggle,
+ Toggle errorToggle, Toggle fatalToggle, GameObject logItemPrefabObj)
+ {
+ consolePage = page;
+ logScrollRect = logScroll;
+ logContent = logContentTransform;
+ detailScrollRect = detailScroll;
+ detailText = detail;
+ clearButton = clearBtn;
+ lockScrollToggle = lockToggle;
+ infoFilterToggle = infoToggle;
+ warningFilterToggle = warningToggle;
+ errorFilterToggle = errorToggle;
+ fatalFilterToggle = fatalToggle;
+ logItemPrefab = logItemPrefabObj;
+ }
+ #endregion
+
+ #region IDebugModule 实现
+ public void Initialize()
+ {
+ Debug.Log("[ConsoleModule] 初始化控制台模块...");
+
+ // 检查必要的组件
+ if (consolePage == null)
+ Debug.LogError("[ConsoleModule] consolePage is null!");
+ if (logScrollRect == null)
+ Debug.LogError("[ConsoleModule] logScrollRect is null!");
+ if (logContent == null)
+ Debug.LogError("[ConsoleModule] logContent is null!");
+ if (detailScrollRect == null)
+ Debug.LogError("[ConsoleModule] detailScrollRect is null!");
+ if (detailText == null)
+ Debug.LogError("[ConsoleModule] detailText is null!");
+ if (clearButton == null)
+ Debug.LogError("[ConsoleModule] clearButton is null!");
+ if (logItemPrefab == null)
+ Debug.LogError("[ConsoleModule] logItemPrefab is null!");
+
+ // 注册Unity日志回调
+ Application.logMessageReceived += OnLogMessageReceived;
+
+ // 设置按钮事件
+ if (clearButton != null)
+ clearButton.onClick.AddListener(ClearAllLogs);
+
+ // 设置Toggle事件
+ if (lockScrollToggle != null)
+ {
+ lockScrollToggle.isOn = lockScroll;
+ lockScrollToggle.onValueChanged.AddListener(OnLockScrollChanged);
+ }
+
+ if (infoFilterToggle != null)
+ {
+ infoFilterToggle.isOn = infoFilter;
+ infoFilterToggle.onValueChanged.AddListener(OnInfoFilterChanged);
+ }
+
+ if (warningFilterToggle != null)
+ {
+ warningFilterToggle.isOn = warningFilter;
+ warningFilterToggle.onValueChanged.AddListener(OnWarningFilterChanged);
+ }
+
+ if (errorFilterToggle != null)
+ {
+ errorFilterToggle.isOn = errorFilter;
+ errorFilterToggle.onValueChanged.AddListener(OnErrorFilterChanged);
+ }
+
+ if (fatalFilterToggle != null)
+ {
+ fatalFilterToggle.isOn = fatalFilter;
+ fatalFilterToggle.onValueChanged.AddListener(OnFatalFilterChanged);
+ }
+
+ // 清空详情
+ if (detailText != null)
+ detailText.text = "点击日志查看详细信息...";
+
+ Debug.Log("[ConsoleModule] 控制台模块初始化完成");
+ }
+
+ public GameObject GetPage()
+ {
+ return consolePage;
+ }
+
+ public string GetModuleName()
+ {
+ return "控制台";
+ }
+ #endregion
+
+ #region 公共方法
+ ///
+ /// 设置SDF字体
+ ///
+ public void SetSDFFont(TMP_FontAsset fontAsset)
+ {
+ savedFontAsset = fontAsset;
+
+ // 应用到详情文本
+ if (detailText != null && fontAsset != null)
+ {
+ detailText.font = fontAsset;
+ }
+
+ // 刷新已有日志项
+ RefreshLogDisplay();
+ }
+
+ ///
+ /// 获取日志统计信息
+ ///
+ public void GetLogCount(out int info, out int warning, out int error, out int fatal)
+ {
+ RefreshCount();
+ info = infoCount;
+ warning = warningCount;
+ error = errorCount;
+ fatal = fatalCount;
+ }
+
+ ///
+ /// 更新(每帧调用)
+ ///
+ public void Update()
+ {
+ // 如果页面未激活,跳过更新
+ if (consolePage == null || !consolePage.activeSelf)
+ {
+ return;
+ }
+
+ // 先处理延迟刷新
+ if (needRefresh)
+ {
+ needRefresh = false;
+ lastRefreshFrame = Time.frameCount;
+ RefreshLogDisplay();
+ }
+
+ // 如果锁定滚动,自动滚动到底部
+ // 只在刷新后的下一帧设置,避免rebuild loop
+ if (lockScroll && logScrollRect != null && Time.frameCount > lastRefreshFrame + 1)
+ {
+ logScrollRect.verticalNormalizedPosition = 0f;
+ }
+
+ // 更新Toggle文本显示
+ UpdateFilterToggleText();
+ }
+
+ ///
+ /// 销毁
+ ///
+ public void Shutdown()
+ {
+ Application.logMessageReceived -= OnLogMessageReceived;
+ ClearAllLogs();
+ }
+ #endregion
+
+ #region 私有方法
+ private void OnLogMessageReceived(string logMessage, string stackTrace, LogType logType)
+ {
+ // 将Assert转换为Error
+ if (logType == LogType.Assert)
+ {
+ logType = LogType.Error;
+ }
+
+ // 创建日志节点
+ LogNode logNode = LogNode.Create(logType, logMessage, stackTrace);
+ logNodes.Enqueue(logNode);
+
+ // 限制最大行数
+ while (logNodes.Count > maxLine)
+ {
+ logNodes.Dequeue();
+ }
+
+ // 标记需要刷新,而不是立即刷新(避免rebuild loop)
+ needRefresh = true;
+ }
+
+ private void RefreshLogDisplay()
+ {
+ // 如果页面未激活,延迟刷新到下次页面激活时
+ if (consolePage == null || !consolePage.activeSelf)
+ {
+ needRefresh = true;
+ return;
+ }
+
+ if (logContent == null)
+ {
+ Debug.LogError("[ConsoleModule] logContent is null!");
+ return;
+ }
+
+ if (logItemPrefab == null)
+ {
+ Debug.LogError("[ConsoleModule] logItemPrefab is null!");
+ return;
+ }
+
+ // 回收所有激活的日志项
+ foreach (var item in activeLogItems)
+ {
+ if (item != null)
+ {
+ item.SetActive(false);
+ if (!logItemPool.Contains(item))
+ {
+ logItemPool.Add(item);
+ }
+ }
+ }
+ activeLogItems.Clear();
+
+ // 遍历日志节点并创建UI
+ int index = 0;
+ int displayCount = 0;
+ foreach (LogNode logNode in logNodes)
+ {
+ // 根据过滤器判断是否显示
+ if (!ShouldShowLog(logNode.LogType))
+ continue;
+
+ // 从对象池获取或创建日志项
+ GameObject logItem = GetLogItemFromPool();
+ if (logItem == null)
+ {
+ Debug.LogError("[ConsoleModule] Failed to get log item from pool!");
+ continue;
+ }
+
+ logItem.transform.SetParent(logContent, false);
+ logItem.SetActive(true);
+ activeLogItems.Add(logItem);
+
+ // 调试:确认对象状态
+ if (!logItem.activeSelf)
+ {
+ Debug.LogWarning($"[ConsoleModule] LogItem {logItem.name} is not active after SetActive(true)!");
+ }
+
+ // 设置日志项内容
+ SetupLogItem(logItem, logNode, index);
+
+ index++;
+ displayCount++;
+ }
+ }
+
+ private bool ShouldShowLog(LogType logType)
+ {
+ switch (logType)
+ {
+ case LogType.Log:
+ return infoFilter;
+ case LogType.Warning:
+ return warningFilter;
+ case LogType.Error:
+ return errorFilter;
+ case LogType.Exception:
+ return fatalFilter;
+ default:
+ return true;
+ }
+ }
+
+ private GameObject GetLogItemFromPool()
+ {
+ if (logItemPool.Count > 0)
+ {
+ GameObject item = logItemPool[0];
+ logItemPool.RemoveAt(0);
+ return item;
+ }
+ else
+ {
+ if (logItemPrefab == null)
+ {
+ Debug.LogError("[ConsoleModule] logItemPrefab is null!");
+ return null;
+ }
+
+ // 创建新的日志项
+ GameObject newItem = UnityEngine.Object.Instantiate(logItemPrefab);
+ newItem.name = "LogItem_" + activeLogItems.Count;
+ return newItem;
+ }
+ }
+
+ private void SetupLogItem(GameObject logItem, LogNode logNode, int index)
+ {
+ if (logItem == null)
+ {
+ Debug.LogError("[ConsoleModule] logItem is null in SetupLogItem!");
+ return;
+ }
+
+ // 获取日志项的Toggle和Text组件
+ Toggle toggle = logItem.GetComponent();
+ TMP_Text text = logItem.GetComponentInChildren();
+
+ if (toggle == null)
+ {
+ Debug.LogWarning($"[ConsoleModule] Toggle component not found on {logItem.name}!");
+ }
+
+ if (text == null)
+ {
+ Debug.LogWarning($"[ConsoleModule] TMP_Text component not found on {logItem.name}!");
+ return;
+ }
+
+ // 设置文本内容和颜色
+ Color32 color = GetLogStringColor(logNode.LogType);
+ string logText = GetLogString(logNode);
+
+ text.text = logText;
+ text.color = color;
+
+ // 应用字体
+ if (savedFontAsset != null)
+ {
+ text.font = savedFontAsset;
+ }
+
+ if (toggle != null)
+ {
+ // 设置Toggle状态
+ toggle.isOn = (selectedNode == logNode);
+
+ // 设置Toggle事件
+ toggle.onValueChanged.RemoveAllListeners();
+ toggle.onValueChanged.AddListener((isOn) =>
+ {
+ if (isOn)
+ {
+ OnLogItemSelected(logNode);
+ }
+ });
+ }
+ }
+
+ private void OnLogItemSelected(LogNode logNode)
+ {
+ selectedNode = logNode;
+
+ // 显示详细信息
+ if (detailText != null && logNode != null)
+ {
+ Color32 color = GetLogStringColor(logNode.LogType);
+ string colorHex = ColorUtility.ToHtmlStringRGBA(color);
+
+ string detailInfo = $"{logNode.LogMessage}\n\n";
+ detailInfo += $"时间: {logNode.LogTime.ToLocalTime():HH:mm:ss.fff}\n";
+ detailInfo += $"帧数: {logNode.LogFrameCount}\n";
+ detailInfo += $"类型: {logNode.LogType}\n\n";
+
+ if (!string.IsNullOrEmpty(logNode.StackTrace))
+ {
+ detailInfo += $"堆栈跟踪:\n{logNode.StackTrace}";
+ }
+
+ detailText.text = detailInfo;
+ }
+
+ // 重置详情滚动位置
+ if (detailScrollRect != null)
+ {
+ detailScrollRect.verticalNormalizedPosition = 1f;
+ }
+ }
+
+ private string GetLogString(LogNode logNode)
+ {
+ return $"[{logNode.LogTime.ToLocalTime():HH:mm:ss.fff}][{logNode.LogFrameCount}] {logNode.LogMessage}";
+ }
+
+ private Color32 GetLogStringColor(LogType logType)
+ {
+ switch (logType)
+ {
+ case LogType.Log:
+ return infoColor;
+ case LogType.Warning:
+ return warningColor;
+ case LogType.Error:
+ return errorColor;
+ case LogType.Exception:
+ return fatalColor;
+ default:
+ return Color.white;
+ }
+ }
+
+ private void RefreshCount()
+ {
+ infoCount = 0;
+ warningCount = 0;
+ errorCount = 0;
+ fatalCount = 0;
+
+ foreach (LogNode logNode in logNodes)
+ {
+ switch (logNode.LogType)
+ {
+ case LogType.Log:
+ infoCount++;
+ break;
+ case LogType.Warning:
+ warningCount++;
+ break;
+ case LogType.Error:
+ errorCount++;
+ break;
+ case LogType.Exception:
+ fatalCount++;
+ break;
+ }
+ }
+ }
+
+ private void UpdateFilterToggleText()
+ {
+ RefreshCount();
+
+ if (infoFilterToggle != null)
+ {
+ var label = infoFilterToggle.GetComponentInChildren();
+ if (label != null)
+ label.text = $"Info ({infoCount})";
+ }
+
+ if (warningFilterToggle != null)
+ {
+ var label = warningFilterToggle.GetComponentInChildren();
+ if (label != null)
+ label.text = $"Warning ({warningCount})";
+ }
+
+ if (errorFilterToggle != null)
+ {
+ var label = errorFilterToggle.GetComponentInChildren();
+ if (label != null)
+ label.text = $"Error ({errorCount})";
+ }
+
+ if (fatalFilterToggle != null)
+ {
+ var label = fatalFilterToggle.GetComponentInChildren();
+ if (label != null)
+ label.text = $"Fatal ({fatalCount})";
+ }
+ }
+
+ private void ClearAllLogs()
+ {
+ logNodes.Clear();
+ selectedNode = null;
+
+ if (detailText != null)
+ detailText.text = "点击日志查看详细信息...";
+
+ RefreshLogDisplay();
+
+ Debug.Log("[ConsoleModule] 已清空所有日志");
+ }
+
+ private void OnLockScrollChanged(bool value)
+ {
+ lockScroll = value;
+ }
+
+ private void OnInfoFilterChanged(bool value)
+ {
+ infoFilter = value;
+ needRefresh = true;
+ }
+
+ private void OnWarningFilterChanged(bool value)
+ {
+ warningFilter = value;
+ needRefresh = true;
+ }
+
+ private void OnErrorFilterChanged(bool value)
+ {
+ errorFilter = value;
+ needRefresh = true;
+ }
+
+ private void OnFatalFilterChanged(bool value)
+ {
+ fatalFilter = value;
+ needRefresh = true;
+ }
+ #endregion
+ }
+}
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/Runtime/ConsoleModule.cs.meta b/Packages/com.bywaystudios.meowmentdebugtool/Runtime/ConsoleModule.cs.meta
new file mode 100644
index 0000000..d9de75b
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/Runtime/ConsoleModule.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1660ec87345f07e4992b23d662f497dc
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.bywaystudios.meowmentdebugtool/Runtime/CustomButtonsModule.cs b/Packages/com.bywaystudios.meowmentdebugtool/Runtime/CustomButtonsModule.cs
new file mode 100644
index 0000000..f7d3205
--- /dev/null
+++ b/Packages/com.bywaystudios.meowmentdebugtool/Runtime/CustomButtonsModule.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Reflection;
+using UnityEngine;
+using UnityEngine.UI;
+using TMPro;
+
+namespace MeowmentDebugTool
+{
+ ///
+ /// 自定义按钮模块 - 通过反射加载标记为DebugButton的方法
+ ///
+ public class CustomButtonsModule : IDebugModule
+ {
+ #region 字段
+ private GameObject customButtonsPage;
+ private RectTransform buttonContainer;
+ private GameObject buttonPrefab;
+ private ScrollRect buttonsScrollRect;
+
+ // 自定义按钮回调
+ private Action