You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中启动外部进程如何避免编辑器冻结并读取输出?

解决Unity调用外部进程时编辑器冻结的问题

你的问题出在同步读取标准输出上:motion.StandardOutput.ReadLine()是阻塞式调用,当外部进程没有输出时,这个方法会卡住Unity的主线程,直接导致编辑器冻结——哪怕你在单独线程启动进程,读取操作还是在Update(主线程)里执行的,根本没解决阻塞问题。

以下是可行的解决方案,核心思路是异步读取外部进程输出,再把数据传到主线程处理:

using UnityEngine;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;

public class StdIOHandler : MonoBehaviour
{
    // 线程安全队列,存储外部进程输出的数据
    private readonly ConcurrentQueue<string> _outputQueue = new ConcurrentQueue<string>();
    private Process _externalProcess;

    void Start()
    {
        try
        {
            _externalProcess = new Process();
            _externalProcess.StartInfo.CreateNoWindow = true;
            _externalProcess.StartInfo.RedirectStandardOutput = true;
            _externalProcess.StartInfo.UseShellExecute = false;
            _externalProcess.StartInfo.FileName = "cmd.exe";
            string batPath = @"C:\Users\gummi\Desktop\hallow3\motion\demo\motion.bat";
            _externalProcess.StartInfo.Arguments = $"/c \"{batPath}\""; // 给路径加引号,避免空格导致命令执行失败

            // 绑定输出接收事件,异步处理外部进程输出
            _externalProcess.OutputDataReceived += (sender, e) =>
            {
                if (!string.IsNullOrEmpty(e.Data))
                {
                    _outputQueue.Enqueue(e.Data);
                }
            };

            // 允许进程触发事件
            _externalProcess.EnableRaisingEvents = true;
            // 启动进程并开始异步读取输出
            _externalProcess.Start();
            _externalProcess.BeginOutputReadLine();
        }
        catch (Exception e)
        {
            Debug.LogError($"启动进程失败: {e.Message}");
        }
    }

    void Update()
    {
        // 主线程从队列批量取数据,无阻塞
        while (_outputQueue.TryDequeue(out string data))
        {
            Debug.Log($"收到外部数据: {data}");
        }
    }

    void OnDestroy()
    {
        // 清理资源,防止外部进程残留
        if (_externalProcess != null && !_externalProcess.HasExited)
        {
            _externalProcess.Kill();
        }
        _externalProcess?.Dispose();
    }
}

关键改动说明:

  • 使用ConcurrentQueue存储输出:保证多线程读写的安全性,因为输出事件是在后台线程触发的。
  • 绑定OutputDataReceived事件:外部进程有输出时自动触发,异步读取不会阻塞主线程。
  • 调用BeginOutputReadLine():启动系统级的异步读取流程,无需手动管理线程。
  • 在Update中批量处理队列数据:主线程安全调用Unity API,避免跨线程操作日志的问题。
  • 增加OnDestroy清理逻辑:防止Unity停止运行后,外部进程在后台残留。

内容的提问来源于stack exchange,提问作者MuSolar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 01:46:47