Project

General

Profile

测试新闻1

用于测试新闻功能
Added by Zane Zane 17 days ago

是的,你可以 单独开一个线程专门用于写日志文件,这样即使主线程(比如 Unity 游戏逻辑线程)崩溃了,只要进程还在运行、日志线程没崩溃,就尽可能地保留错误发生前的关键信息。这是一种更稳健的日志方案,适用于排查崩溃前的上下文。


✅ 原理

  1. Unity 的 Application.logMessageReceivedThreaded 可以在任意线程中接收到日志(包括崩溃前的线程)
  2. 你可以将日志信息写入一个线程安全的队列
  3. 然后由一个专属日志写入线程将队列中的内容实时写入自定义日志文件

✅ 示例代码:多线程日志系统

using UnityEngine;
using System.Collections.Concurrent;
using System.Threading;
using System.IO;

public class ThreadedLogger : MonoBehaviour
{
    private ConcurrentQueue<string> logQueue = new ConcurrentQueue<string>();
    private Thread logThread;
    private bool isRunning = true;
    private StreamWriter logWriter;

    void Awake()
    {
        string fileName = $"Log_{System.DateTime.Now:yyyy-MM-dd_HH-mm-ss}.txt";
        string filePath = Path.Combine(Application.persistentDataPath, fileName);
        logWriter = new StreamWriter(filePath, true) { AutoFlush = true };

        // 注册全局日志事件(主线程 + 子线程)
        Application.logMessageReceivedThreaded += OnLogMessage;

        // 启动日志线程
        logThread = new Thread(LogWriterThread);
        logThread.IsBackground = true;
        logThread.Start();
    }

    void OnLogMessage(string condition, string stackTrace, LogType type)
    {
        string timestamp = System.DateTime.Now.ToString("HH:mm:ss.fff");
        string logEntry = $"[{timestamp}] [{type}] {condition}";
        if (type == LogType.Exception || type == LogType.Error)
        {
            logEntry += $"\n{stackTrace}";
        }

        logQueue.Enqueue(logEntry);
    }

    void LogWriterThread()
    {
        while (isRunning)
        {
            while (logQueue.TryDequeue(out string log))
            {
                logWriter.WriteLine(log);
            }
            Thread.Sleep(10); // 减少 CPU 占用
        }
    }

    void OnDestroy()
    {
        isRunning = false;
        logThread?.Join();

        Application.logMessageReceivedThreaded -= OnLogMessage;
        logWriter?.Close();
    }
}

🔒 补充说明

  • 使用 ConcurrentQueue 保证线程安全
  • logThread 设置为后台线程(IsBackground = true),确保进程结束时不阻塞
  • 比 Unity 默认的 Player.log 更可靠,尤其适合临近崩溃的瞬间

⚠️ 注意:

  • 如果是 原生崩溃(如内存越界),Unity 进程可能直接被系统杀掉,这时候任何线程都不能再运行(包括你自建的日志线程)
  • 这个方案仍然大概率能捕捉绝大部分未处理异常或错误导致的崩溃

是否还需要我帮你集成这套日志系统到上传工单(Web)功能中?也可以加上崩溃前系统信息(SystemInfo)自动打包。


Comments