在WPF应用程序中嵌入Unity3D应用程序

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

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

我在团结论坛上问了这个问题,找不到任何好的答案,所以要求更多的观众。

这可以做到,但值得注意的是它只能在Windows上运行。

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

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

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

以下是Unity网站上嵌入代码的完整示例。 你可以在这里获得整个项目。 确保将Unity的构建exe文件命名为“UnityGame.exe”,然后将其放在与WPF exe程序相同的目录中。

 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(); } } }