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

查看:1358
本文介绍了在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

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 + ".\nCheck 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天全站免登陆