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

能否在Unity自定义Editor Window中嵌入运行第三方exe或自有桌面应用?

Unity EditorWindow嵌入外部exe桌面应用的可行方案

完全可以实现,主流有两种适配不同场景的实现方案:

方案1:Windows原生窗口嵌入(支持无源码的第三方exe、自有exe)

这个方案是Windows平台下成本最低的实现方式,核心原理是通过Win32 API将外部exe的主窗口设置为Unity EditorWindow的子窗口,直接复用exe本身的渲染和交互逻辑,不需要修改目标exe的源码,用来嵌入cmd这类系统工具非常合适。

核心实现步骤:

  • 通过C#的Process类启动目标exe,等待程序初始化完成后获取它的主窗口句柄
  • 调用EditorWindowUtils.GetWindowHandle获取当前自定义EditorWindow的原生窗口句柄
  • 调用Win32 APISetParent将exe窗口绑定为EditorWindow的子窗口,再去掉exe窗口的标题栏、边框等样式
  • 监听EditorWindow的大小变化事件,同步调整内嵌exe窗口的尺寸填满整个EditorWindow客户区

示例核心代码如下:

using UnityEditor;
using UnityEngine;
using System.Diagnostics;
using System.Runtime.InteropServices;

public class ExeEmbedWindow : EditorWindow
{
    // 引入需要的Win32 API
    [DllImport("user32.dll")]
    private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    [DllImport("user32.dll")]
    private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
    [DllImport("user32.dll", SetLastError = true)]
    private static extern int SetWindowLongPtr(IntPtr hWnd, int nIndex, int dwNewLong);
    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    private Process _targetProcess;
    private IntPtr _exeWindowHandle = IntPtr.Zero;

    [MenuItem("Window/Embedded Exe Demo")]
    public static void OpenWindow()
    {
        GetWindow<ExeEmbedWindow>("内嵌exe窗口");
    }

    private void OnEnable()
    {
        // 启动目标exe,此处以cmd.exe为例
        ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe")
        {
            UseShellExecute = true
        };
        _targetProcess = Process.Start(startInfo);
        // 等待程序初始化完成,部分启动慢的exe可以加个几百毫秒的延迟
        _targetProcess.WaitForInputIdle(2000);
        _exeWindowHandle = _targetProcess.MainWindowHandle;

        if (_exeWindowHandle == IntPtr.Zero)
        {
            UnityEngine.Debug.LogError("获取exe窗口句柄失败");
            return;
        }

        // 获取当前EditorWindow的原生句柄,Unity 2020及以上版本支持该API
        IntPtr unityWindowHandle = EditorWindowUtils.GetWindowHandle(this);
        // 绑定父子窗口关系
        SetParent(_exeWindowHandle, unityWindowHandle);
        // 移除exe窗口的边框、标题栏等样式,仅保留可视属性
        SetWindowLongPtr(_exeWindowHandle, -16 /* GWL_STYLE */, 0x10000000 /* WS_VISIBLE */);
        // 调整初始大小
        MoveWindow(_exeWindowHandle, 0, 0, (int)position.width, (int)position.height, true);
    }

    private void OnGUI()
    {
        // 窗口大小变化时同步调整内嵌exe的尺寸
        if (_exeWindowHandle != IntPtr.Zero)
        {
            MoveWindow(_exeWindowHandle, 0, 0, (int)position.width, (int)position.height, true);
        }
    }

    private void OnDisable()
    {
        // 窗口关闭时主动杀掉进程,避免后台残留
        if (_targetProcess != null && !_targetProcess.HasExited)
        {
            _targetProcess.Kill();
            _targetProcess.Dispose();
        }
        _exeWindowHandle = IntPtr.Zero;
    }
}

方案2:跨平台帧传输方案(仅适用于可修改源码的自有桌面应用)

如果你需要在macOS、Linux等非Windows平台也实现嵌入,或者需要对嵌入的应用做更多自定义控制,可以选择帧传输方案:

  • 给你的自有桌面应用新增采集模块,实时捕获应用的渲染帧,通过本地Socket或者共享内存传输给Unity
  • Unity的EditorWindow收到帧数据后转成Texture2D,直接绘制在窗口的GUI区域
  • 将EditorWindow内捕获的键盘、鼠标输入事件,反向传输给桌面应用执行对应的交互操作

这个方案的优势是完全跨平台,不受系统原生API限制,也不会出现窗口权限导致的兼容性问题,但需要你有桌面应用的源码可以做二次开发,不适用第三方无源码的exe。

常见注意事项

  • 原生窗口嵌入方案仅支持Windows平台,macOS/Linux需要对应替换为Cocoa/X11的原生API实现父子窗口绑定逻辑
  • 部分使用DirectX 12、Vulkan渲染的高权限exe可能出现画面闪烁、输入无响应的问题,可尝试关闭exe的硬件加速选项解决
  • 内嵌exe的快捷键可能和Unity编辑器的全局快捷键冲突,可根据需求自行实现快捷键拦截过滤逻辑
  • 低版本Unity没有EditorWindowUtils.GetWindowHandleAPI,可以通过Win32的FindWindow接口按窗口标题匹配获取EditorWindow的句柄

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 09:15:02