博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF内嵌Unity并实现双向通讯
阅读量:5248 次
发布时间:2019-06-14

本文共 3216 字,大约阅读时间需要 10 分钟。

引自:http://www.unitymanual.com/blog-11491-1628.html

博客原文:

http://www.lolofinil.com/2014/10/10/wpf-unity-embed-pipes

说明

需求是这样的 —— 一个编辑器。既能够方便得编辑各种静态数据表(Excel),又能够对表中指定的资源进行预览(Spine骨骼动画)。

在于适合做表编辑器的软件框架,如WPF、Winform等等,都没有相应的Spine渲染库;而支持Spine渲染的框架,如、MonoGame、Cocos2D等,又或存在Excel库不好用或者缺少软件向控件的问题。

我们采取的方案是,使用WPF做它擅长的软件功能,而使用Unity作为“渲染控件”。

技术路线

为什么不用WPF嵌入?

将Unity嵌入WPF(或Winform),比较常见的做法是通过ActiveX将UnityWebPlayer包装成一个真正的控件。但由于UnityWebPlayer运行在安全沙箱中,它至少有以下两个问题:

  • 没有System.IO的程序集,只能够加载assetbundle,无法加载未经管线预处理的Spine
  • 没法加载Excel文件
  • 如何将Unity Windows Standalone 嵌入WPF
    将Standalone作为一个控件,指定到WPF父窗口下。采用WindowsAPI来实现。

如何实现Standalone与WPF双向通信

需要能在WPF中设定Standalone的当前Spine,也要能在Standalone上操作由WPF维护的Excel。一个可行的方案是pipes。
中说Unity不初始化NamedPipelineServer。那么就拿它当NamedPipelineClient好了。

将Unity Windows Standalone 嵌入WPF

核心代码如下:

// 定义一个WPF用户控件,来定义Standalone的尺寸
ProcessStartInfo info = new ProcessStartInfo(“UnityControl.exe”);
info.UseShellExecute = true;
info.WindowStyle = ProcessWindowStyle.Minimized;
m_AppProcess = System.Diagnostics.Process.Start(info);
m_AppProcess.WaitForInputIdle();
this.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.ApplicationIdle,
appIdleEvent, this, null);

// Application Idle 事件处理WindowInteropHelper helper = new WindowInteropHelper(Window.GetWindow(this));IntPtr ptr = helper.Handle;SetParent(app.MainWindowHandle, helper.Handle);SetWindowLong(new HandleRef(this, app.MainWindowHandle), GWL_STYLE, WS_VISIBLE); MoveWindow(app.MainWindowHandle, (int)control.Margin.Left, (int)control.Margin.Top, (int)control.Width, (int)control.Height, true);

实现Unity Windows Standalone与WPF通讯

// WPFNamedPipeServerStream pipeServer = new NamedPipeServerStream(    "testpipe",     PipeDirection.InOut,     1);pipeServer.WaitForConnection();string str = "hello from server!"; byte[] outBuffer = Encoding.Unicode.GetBytes(str); int len = outBuffer.Length; pipeServer.WriteByte((byte)(len / 256)); pipeServer.WriteByte((byte)(len % 256)); pipeServer.Write(outBuffer, 0, len); pipeServer.Flush(); len = pipeServer.ReadByte() * 256; len += pipeServer.ReadByte(); byte[] inBuffer = new byte[len]; pipeServer.Read(inBuffer, 0, len); string remoteInfo = Encoding.Unicode.GetString(inBuffer); lbRemoteInfo.Content = remoteInfo; // Unity pipeClient = new NamedPipeClientStream( ".", "testpipe", PipeDirection.InOut); pipeClient.Connect(10000); int len = pipeClient.ReadByte() * 256; len += pipeClient.ReadByte(); byte[] inBuffer = new byte[len]; pipeClient.Read(inBuffer, 0, len); remoteInfo = Encoding.Unicode.GetString(inBuffer); pipeClient.Flush(); string str = "hello from client!"; byte[] outBuffer = Encoding.Unicode.GetBytes(str); len = outBuffer.Length; pipeClient.WriteByte((byte)(len / 256)); pipeClient.WriteByte((byte)(len % 256)); pipeClient.Write(outBuffer, 0, len); pipeClient.Flush();

效果

做了一个简单的测试,看上去效果不错:

  • Unity(Client)被嵌入WPF(Server)窗口
  • WPF向Unity发送一条”hello from server!”,在Unity控件的左上角显示
  • Unity向WPF发送一条”hello from client!”,显示在一个WPF的Label上

说明和参考

MSDN管道通讯Demo

Mono不支持管道安全级别

不用就可以了,NamedPipeServerStream构造函数里,不要填TokenImpersonationLevel

Unity无法启动NamedPipelineServer

在Unity中启用System.IO.Pipes命名空间

在Player Settings中,将.net版本设置为.net2.0,默认是.net2.0 subset

如何将窗体嵌入为控件

转载于:https://www.cnblogs.com/nearpengju123/p/4494573.html

你可能感兴趣的文章
简单的聊天脑思路
查看>>
java web项目修改favicon.ico图标的方式
查看>>
【读博笔记】 如何招聘程序员,四步法则助你成功
查看>>
Struts框架----进度1
查看>>
783. Minimum Distance Between BST Node
查看>>
剑指Offer——合并两个排序的链表
查看>>
剑指Offer——机器人的运动范围
查看>>
day01_Sock Merchant
查看>>
Round B APAC Test 2017
查看>>
Office 365 系列一 ------- 如何单个安装Office 客户端和Skype for business
查看>>
MySQL 字符编码问题详细解释
查看>>
perl 学习笔记
查看>>
31 Days of Windows Phone
查看>>
poj 1184(聪明的打字员)
查看>>
Ubuntu下面安装eclipse for c++
查看>>
C#压缩或解压(rar和zip文件)
查看>>
观察者模式
查看>>
电商网站的宕机案例分析
查看>>
查看Linux端口的占用及连接情况
查看>>
让IE浏览器支持CSS3圆角属性的方法
查看>>