简易版log程序

以下是一个简易的Unity日志工具实现,包含分类显示、基础过滤和手机摇动触发功能:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;

public enum LogTypeFilter
{
    Info = 1,
    Warning = 2,
    Error = 4,
    All = Info | Warning | Error
}

public class SimpleLogTool : MonoBehaviour
{
    private static SimpleLogTool _instance;
    public static SimpleLogTool Instance => _instance;

    [Header("UI References")]
    [SerializeField] private GameObject logPanel;
    [SerializeField] private Text logText;
    [SerializeField] private ScrollRect scrollRect;
    [SerializeField] private Toggle infoToggle;
    [SerializeField] private Toggle warningToggle;
    [SerializeField] private Toggle errorToggle;
    [SerializeField] private InputField searchInput;

    [Header("Settings")]
    [SerializeField] private bool enableShakeToShow = true;
    [SerializeField] private float shakeDetectionThreshold = 2f;
    [SerializeField] private Color infoColor = Color.white;
    [SerializeField] private Color warningColor = Color.yellow;
    [SerializeField] private Color errorColor = Color.red;

    private List<LogEntry> logEntries = new List<LogEntry>();
    private LogTypeFilter currentFilter = LogTypeFilter.All;
    private string searchKeyword = "";
    private Vector3 acceleration;

    private void Awake()
    {
        if (_instance != null && _instance != this)
        {
            Destroy(gameObject);
            return;
        }
        _instance = this;

        Application.logMessageReceived += HandleLog;
    }

    private void Update()
    {
        if (enableShakeToShow && Input.acceleration.sqrMagnitude >= shakeDetectionThreshold)
        {
            ToggleLogPanel();
        }
    }

    private void HandleLog(string logString, string stackTrace, LogType type)
    {
        LogEntry entry = new LogEntry
        {
            content = logString,
            type = ConvertToLogType(type),
            timestamp = System.DateTime.Now.ToString("HH:mm:ss")
        };

        logEntries.Add(entry);
        UpdateLogDisplay();
    }

    private LogTypeFilter ConvertToLogType(LogType unityLogType)
    {
        switch (unityLogType)
        {
            case LogType.Warning:
                return LogTypeFilter.Warning;
            case LogType.Error:
            case LogType.Assert:
            case LogType.Exception:
                return LogTypeFilter.Error;
            default:
                return LogTypeFilter.Info;
        }
    }

    public void ToggleLogPanel()
    {
        logPanel.SetActive(!logPanel.activeSelf);
        if (logPanel.activeSelf)
        {
            UpdateLogDisplay();
        }
    }

    public void OnFilterChanged()
    {
        currentFilter = (LogTypeFilter)(
            (infoToggle.isOn ? (int)LogTypeFilter.Info : 0) |
            (warningToggle.isOn ? (int)LogTypeFilter.Warning : 0) |
            (errorToggle.isOn ? (int)LogTypeFilter.Error : 0)
        );
        UpdateLogDisplay();
    }

    public void OnSearchInputChanged()
    {
        searchKeyword = searchInput.text.ToLower();
        UpdateLogDisplay();
    }

    public void ClearLogs()
    {
        logEntries.Clear();
        UpdateLogDisplay();
    }

    private void UpdateLogDisplay()
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        foreach (var entry in logEntries)
        {
            if ((currentFilter & entry.type) == 0) continue;
            if (!string.IsNullOrEmpty(searchKeyword) && 
                !entry.content.ToLower().Contains(searchKeyword)) continue;

            sb.AppendLine($"<color={GetColorHex(entry.type)}>[{entry.type}] {entry.timestamp} - {entry.content}</color>");
        }
        logText.text = sb.ToString();
        Canvas.ForceUpdateCanvases();
        scrollRect.verticalNormalizedPosition = 0;
    }

    private string GetColorHex(LogTypeFilter type)
    {
        switch (type)
        {
            case LogTypeFilter.Info: return $"#{ColorUtility.ToHtmlStringRGB(infoColor)}";
            case LogTypeFilter.Warning: return $"#{ColorUtility.ToHtmlStringRGB(warningColor)}";
            case LogTypeFilter.Error: return $"#{ColorUtility.ToHtmlStringRGB(errorColor)}";
            default: return "white";
        }
    }

    private struct LogEntry
    {
        public string content;
        public LogTypeFilter type;
        public string timestamp;
    }
}

使用步骤:

  1. 创建一个Canvas并添加以下UI元素:

    • Panel(作为日志窗口)
    • Scroll View包含Text用于显示日志
    • 三个Toggle分别对应Info/Warning/Error过滤
    • InputField用于搜索
    • 一个清除按钮
  2. 将脚本挂载到场景中的空物体上

  3. 在Inspector中关联各个UI引用

功能特点:

  • 自动捕获Unity日志(包括异常)
  • 分类显示(Info/Warning/Error)
  • 颜色区分不同类型日志
  • 关键词搜索过滤
  • 摇动手机切换显示/隐藏(移动端)
  • 实时更新日志显示
  • 手动清除日志功能
  • 类型过滤组合功能

扩展建议:

  1. 添加日志上限限制防止内存溢出
  2. 增加日志导出功能
  3. 添加对象池优化大量日志的性能
  4. 增加堆栈跟踪显示
  5. 添加日志文件保存功能
  6. 增加屏幕日志打印功能(类似手机端的悬浮窗)

注意事项:

  1. 需要在Unity中设置好UI层级关系
  2. 根据项目需求调整颜色和阈值参数
  3. 移动端使用时建议适当调高shakeDetectionThreshold值
  4. 长时间运行建议添加日志数量限制

这个工具可以帮助开发者在真机调试时快速查看日志信息,并通过过滤功能快速定位问题,比Unity默认的Console窗口更适合移动端调试使用。

此条目发表在工具分类目录。将固定链接加入收藏夹。