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

如何将单个Unity .exe进程嵌入多个WPF Page实现不同场景切换显示

实现方案

完全可以实现同一运行态Unity进程多页面复用、后台保活的需求,不需要每次导航重启Unity进程,具体实现思路如下:


1. 核心逻辑改造点

不要将Unity嵌入逻辑绑定到单个Page,而是把Unity进程、承载用的WinForms Panel都做成全局单例,仅在程序启动时初始化一次,页面导航时仅做宿主容器的挂载/卸载操作,不触碰Unity进程本身。


2. 具体实现步骤

  • 第一步:构建全局Unity管理单例

    封装静态管理类,统一处理Unity进程启动、承载Panel的缓存、挂载卸载逻辑,核心代码参考如下:

    public static class UnityHostManager
    {
        // 全局唯一的Unity承载WinForms Panel
        public static System.Windows.Forms.Panel UnityPanel { get; private set; }
        // 全局唯一的Unity进程实例
        public static Process UnityProcess { get; private set; }
        // 后台缓存用的隐藏宿主,无页面展示时存储UnityPanel
        private static WindowsFormsHost _hiddenCacheHost = new WindowsFormsHost { Visibility = Visibility.Hidden };
    
        // 程序启动时仅调用一次,初始化Unity进程和嵌入逻辑
        public static void InitUnity()
        {
            if (UnityProcess != null) return;
            UnityPanel = new System.Windows.Forms.Panel();
            // 此处复用你原有启动Unity进程、获取窗口句柄、嵌入到Panel的逻辑
            // ......原有嵌入代码......
            // 初始化后先放入隐藏缓存宿主
            _hiddenCacheHost.Child = UnityPanel;
        }
    
        // 将Unity Panel挂载到当前页面的WindowsFormsHost
        public static void AttachToPageHost(WindowsFormsHost currentPageHost)
        {
            if (UnityPanel == null) InitUnity();
            // 先从原有父容器卸载
            var oldHost = UnityPanel.Parent as WindowsFormsHost;
            if (oldHost != null) oldHost.Child = null;
            // 挂载到当前页面的宿主
            currentPageHost.Child = UnityPanel;
            // 可选:发送重绘消息避免Unity窗口错位黑屏
        }
    
        // 将Unity Panel卸载回后台缓存
        public static void DetachToCache()
        {
            if (UnityPanel == null) return;
            var currentHost = UnityPanel.Parent as WindowsFormsHost;
            if (currentHost != null) currentHost.Child = null;
            _hiddenCacheHost.Child = UnityPanel;
        }
    }
    

    可以在App.xaml.cs的OnStartup方法中调用UnityHostManager.InitUnity(),程序启动时就初始化Unity进程,也可以懒加载在第一次进入带Unity的页面时初始化。

  • 第二步:改造带Unity展示的页面逻辑

    每个需要展示Unity的Page的XAML还是保留原有结构,只需要给WindowsFormsHost命名即可:

    <WindowsFormsHost x:Name="UnityHostContainer"/>
    

    在页面的Loaded和Unloaded事件中处理挂载、卸载逻辑,同时调用你已有的TCP接口切换对应场景:

    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        UnityHostManager.AttachToPageHost(UnityHostContainer);
        // 调用TCP接口,通知Unity切换到当前页面对应的场景,比如Page1发切Scene1的指令
    }
    
    private void Page_Unloaded(object sender, RoutedEventArgs e)
    {
        UnityHostManager.DetachToCache();
    }
    
  • 第三步:无Unity页面的后台保活处理

    导航到不需要展示Unity的普通页面时,不需要做任何额外操作,Unity进程会一直运行在后台,承载Panel放在隐藏的缓存宿主中不会被销毁,TCP连接也可以保持,下次进入带Unity的页面时直接挂载即可,不需要重新加载。


3. 可选优化方案

你提到的UserControl方案完全可行,可以把挂载卸载逻辑封装到一个UnityHostUserControl中,每个需要展示Unity的Page直接放置这个UserControl即可,不需要每个页面重复写Loaded/Unloaded事件逻辑,复用性更高。


注意事项

  • 挂载完成后可以给Unity窗口发送重绘消息,或者调用SetWindowPos刷新位置,避免出现黑屏、错位问题
  • WPF程序退出时要主动杀掉Unity进程,避免留下孤儿后台进程
  • 多页面切换场景时可以加个过渡动画,掩盖Unity场景加载的间隙,提升体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 12:45:03