在 WPF 应用程序中嵌入 Unity3D 应用程序
Posted
技术标签:
【中文标题】在 WPF 应用程序中嵌入 Unity3D 应用程序【英文标题】:Embed Unity3D app inside WPF application 【发布时间】:2017-05-18 23:18:08 【问题描述】:我想在 WPF 中开发一个新的 CAD 软件,而不是使用 WPF 3D,是否可以使用 Unity3D 作为我的图形引擎,它能够根据我的数据对象旋转、平移、缩放和查看 3D 图形对象WPF?
我问这个问题的原因是,Unity 是一个游戏引擎,它使用 C# 作为脚本,但它不提供来自 WPF 应用程序的任何集成(将 Unity 嵌入到 WPF 中)。
我在统一论坛上问过这个问题,找不到任何好的答案,所以问更多的观众。
【问题讨论】:
是的,可以使用 Unity。不过说真的,您可以使用任何 3D 游戏引擎进行平移、旋转和缩放,所以我无法说出这个问题的意义。 非常感谢。我修改了我的问题,请看一下。您是否尝试过使用 WPF 作为您的主应用程序并调用 Unity3D 来显示图形显示? 您可以使用 TCP 或 Pipe 在两者之间进行通信,this 的帖子描述了如何将 Unity App 嵌入 WPF。 我会先检查Eyeshot。这是一个专为 CAD 应用程序设计的 WPF 控件。 Unity3D 并不是完全免费的,更多内容在这里:answers.unity3d.com/questions/7720/is-unity-really-free-.html 【参考方案1】:这是可以做到的,但值得注意的是它只适用于 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 或Named Pipes。
以下是来自 Unity 网站的嵌入代码的完整示例。你可以得到整个项目here。确保将 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();
【讨论】:
感谢您的解决方案。看起来这适用于您提供的示例,但对于其他示例则不起作用。可能是什么问题呢?会不会是unity项目的加载时间?我注意到的是统一项目已加载,但未显示在表单中。谢谢 我解决了添加 process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized; 非常棒!您的回答拯救了人类数千小时的生命!很有用 非常感谢。不过,这是针对 Windows 窗体项目的。要使其在 WPF 中工作,请使用 xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"以上是关于在 WPF 应用程序中嵌入 Unity3D 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
将一个 Unity .exe 文件嵌入到多个 WPF 页面中