216 lines
5.5 KiB
Markdown
216 lines
5.5 KiB
Markdown
# 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<TMP_FontAsset>("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正常显示日志
|
||
- ✅ 过滤器正常工作
|
||
- ✅ 滚动功能正常
|
||
- ⚠️ 可能仍有字体警告(如果没有设置中文字体)
|
||
|
||
字体警告不影响功能,只是文本显示为方块。如果需要中文显示,请按照上述方案添加中文字体。
|