MeowmentDebugTool/Packages/com.bywaystudios.meowmentdebugtool/BUGFIX_REBUILD_LOOP.md
2025-12-22 15:29:55 +08:00

5.5 KiB
Raw Blame History

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
private bool needRefresh = false;

// 在OnLogMessageReceived中
needRefresh = true; // 标记需要刷新

// 在Update中
if (needRefresh)
{
    needRefresh = false;
    RefreshLogDisplay(); // 延迟到下一帧刷新
}
  1. 滚动位置延迟设置: 使用帧计数延迟设置滚动位置
private int lastRefreshFrame = -1;

// 只在刷新后的第2帧设置滚动位置
if (lockScroll && Time.frameCount > lastRefreshFrame + 1)
{
    logScrollRect.verticalNormalizedPosition = 0f;
}
  1. 过滤器事件优化: 过滤器改变时也使用延迟刷新
private void OnInfoFilterChanged(bool value)
{
    infoFilter = value;
    needRefresh = true; // 而不是立即RefreshLogDisplay()
}

SettingsModule.cs

  1. 移除ForceUpdateCanvases: Canvas会自动在下一帧更新
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: 使用中文字体 (推荐)

// 在游戏初始化时设置中文字体
UniversalDebugTool.Init();

// 加载支持中文的TMP字体
TMP_FontAsset chineseFont = Resources.Load<TMP_FontAsset>("Fonts/ChineseFont SDF");
UniversalDebugTool.SetSDFFont(chineseFont);

方案2: 禁用字体警告

在RuntimeUIGenerator的GetDefaultFont方法中添加过滤

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修复

void Start()
{
    UniversalDebugTool.Init();
    
    // 快速生成大量日志
    for (int i = 0; i < 100; i++)
    {
        Debug.Log($"测试日志 {i}");
        Debug.LogWarning($"警告 {i}");
        Debug.LogError($"错误 {i}");
    }
    
    // 不应该再有rebuild loop错误
}

2. 测试滚动功能

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方法返回中文字体

最佳实践

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正常显示日志
  • 过滤器正常工作
  • 滚动功能正常
  • ⚠️ 可能仍有字体警告(如果没有设置中文字体)

字体警告不影响功能,只是文本显示为方块。如果需要中文显示,请按照上述方案添加中文字体。