在 WPF 应用程序中嵌入 Unity3D 应用程序 [英] Embed Unity3D app inside WPF application

查看:49
本文介绍了在 WPF 应用程序中嵌入 Unity3D 应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 WPF 中开发一个新的 CAD 软件,而不是使用 WPF 3D,是否可以使用 Unity3D 作为我的图形引擎,该引擎能够根据我的数据对象旋转、平移、缩放和查看 3D 图形对象?WPF?

I want to develop a new CAD software in WPF and instead of using WPF 3D, is it possible to use Unity3D as my graphic engine that is capable of rotate, pan, zoom and view 3D graphic objects based on my data objects in WPF?

我问这个问题的原因是,Unity 是一个游戏引擎,它使用 C# 作为脚本,但它不提供来自 WPF 应用程序的任何集成(将 Unity 嵌入到 WPF 中).

The reason I am asking this question is, Unity is a game engine, it uses C# as script but it does not provide any integration from WPF application (embeds Unity into WPF).

我在统一论坛上问过这个问题,找不到任何好的答案,所以问了更多的观众.

I asked the question in unity forum, could not find any good answer, so asking to a larger audience.

推荐答案

这可以做到,但值得注意的是它只能在 Windows 上工作.

This can be done but it's worth noting that it will only work on Windows.

以前很难做到这一点,但 Unity 最近(4.5.5p1)添加了 -parentHWND 命令可用于将其程序嵌入到另一个程序中.您所要做的就是构建您的 Unity 应用程序,然后从 WPF 使用 Process API 启动它.然后,您可以将 -parentHWND 参数传递给 Unity 应用程序.

It used to be hard to do this but Unity recently(4.5.5p1) added -parentHWND command that can be used to embed its program into another program. All you have to do is build your Unity app, then from WPF, start it with the Process API. You can then pass the -parentHWND parameter to the Unity app.

process.StartInfo.FileName = "YourUnityApp.exe";
process.StartInfo.Arguments = "-parentHWND " + panel1.Handle.ToInt32() + " " + Environment.CommandLine;

对于两者之间的交换,您可以使用 TCP 或 命名管道.

For commutation between the two, you can either use TCP or Named Pipes.

以下是来自 Unity 网站的完整嵌入代码示例.您可以在此处获取整个项目.确保将 Unity 的构建 exe 文件命名为 UnityGame.exe",然后将其放置在与 WPF exe 程序相同的目录中.

Below is a complete sample of the embed code from Unity's website. You can get the whole project here. Make sure to name the Unity's build exe file "UnityGame.exe" then place it in the-same directory as the WPF exe program.

namespace Container
{
    public partial class Form1 : Form
    {
        [DllImport("User32.dll")]
        static extern bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);

        internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);
        [DllImport("user32.dll")]
        internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);

        [DllImport("user32.dll")]
        static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

        private Process process;
        private IntPtr unityHWND = IntPtr.Zero;

        private const int WM_ACTIVATE = 0x0006;
        private readonly IntPtr WA_ACTIVE = new IntPtr(1);
        private readonly IntPtr WA_INACTIVE = new IntPtr(0);

        public Form1()
        {
            InitializeComponent();

            try
            {
                process = new Process();
                process.StartInfo.FileName = "UnityGame.exe";
                process.StartInfo.Arguments = "-parentHWND " + panel1.Handle.ToInt32() + " " + Environment.CommandLine;
                process.StartInfo.UseShellExecute = true;
                process.StartInfo.CreateNoWindow = true;

                process.Start();

                process.WaitForInputIdle();
                // Doesn't work for some reason ?!
                //unityHWND = process.MainWindowHandle;
                EnumChildWindows(panel1.Handle, WindowEnum, IntPtr.Zero);

                unityHWNDLabel.Text = "Unity HWND: 0x" + unityHWND.ToString("X8");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ".
Check if Container.exe is placed next to UnityGame.exe.");
            }

        }

        private void ActivateUnityWindow()
        {
            SendMessage(unityHWND, WM_ACTIVATE, WA_ACTIVE, IntPtr.Zero);
        }

        private void DeactivateUnityWindow()
        {
            SendMessage(unityHWND, WM_ACTIVATE, WA_INACTIVE, IntPtr.Zero);
        }

        private int WindowEnum(IntPtr hwnd, IntPtr lparam)
        {
            unityHWND = hwnd;
            ActivateUnityWindow();
            return 0;
        }

        private void panel1_Resize(object sender, EventArgs e)
        {
            MoveWindow(unityHWND, 0, 0, panel1.Width, panel1.Height, true);
            ActivateUnityWindow();
        }

        // Close Unity application
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
                process.CloseMainWindow();

                Thread.Sleep(1000);
                while (!process.HasExited)
                    process.Kill();
            }
            catch (Exception)
            {

            }
        }

        private void Form1_Activated(object sender, EventArgs e)
        {
            ActivateUnityWindow();
        }

        private void Form1_Deactivate(object sender, EventArgs e)
        {
            DeactivateUnityWindow();
        }
    }
}

这篇关于在 WPF 应用程序中嵌入 Unity3D 应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆