热门标签 | HotTags
当前位置:  开发笔记 > 开发工具 > 正文

WPFUNITY双向通信

说明需求是这样的——一个编辑器。既能够方便得编辑各种静态数据表(Excel),又能够对表中指定的资源进行预览(Spine骨骼动画)。问题在于适合做表编辑器的软件框架,

说明

需求是这样的 —— 一个编辑器。既能够方便得编辑各种静态数据表(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通讯

// WPF
NamedPipeServerStream 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
StackOverflow

Unity无法启动NamedPipelineServer
StackOverflow

在Unity中启用System.IO.Pipes命名空间
在Player Settings中,将.net版本设置为.net2.0,默认是.net2.0 subset
StackOverflow

如何将窗体嵌入为控件
C#自定义控件:WinForm将其它应用程序窗体嵌入自己内部

unity的插件winform


推荐阅读
  • IT项目管理过程中的方法、工具、技术
    工欲善其事,必先利其器。而对于一个软件开发项目,最重要的器就是方法,工具和技术。而这三要素中重要的又是方法论,方法是基础&# ... [详细]
  • 本文详细介绍了C语言中链表的两种动态创建方法——头插法和尾插法,包括具体的实现代码和运行示例。通过这些内容,读者可以更好地理解和掌握链表的基本操作。 ... [详细]
  • 本文详细介绍了Python中文件的基本操作,包括打开、读取、写入和关闭文件的方法,并通过实例展示了如何将Excel文件转换为CSV文件以及进一步转换为HTML文件。此外,还涉及了成绩等级替换的具体实现。 ... [详细]
  • 在过去两周中,我们利用 ReportViewer 开发了与生产良率相关的报表,其中每个制程的直通率是所有测试项良率的乘积。由于 ReportViewer 没有内置的累乘函数,因此需要借助自定义代码来实现这一功能。本文将详细介绍实现步骤和相关代码。 ... [详细]
  • 本文介绍如何使用 Python 获取文件和图片的创建、修改及拍摄日期。通过多种方法,如 PIL 库的 _getexif() 函数和 os 模块的 getmtime() 和 stat() 方法,详细讲解了这些技术的应用场景和注意事项。 ... [详细]
  • NPOI 2.1.3 学习笔记:在Excel中创建多个工作表
    本文介绍如何使用NPOI库在Excel文件中创建多个工作表。通过简单的代码示例,详细讲解了创建和命名工作表的方法,并展示了最终效果。 ... [详细]
  • 本文介绍如何使用 Python 的 xlrd 库读取 Excel 文件,并将其数据处理后存储到数据库中。通过实际案例,详细讲解了文件路径、合并单元格处理等常见问题。 ... [详细]
  • 如何在Excel中批量生成条形码
    本文将详细介绍如何利用Excel快速批量生成条形码,适用于需要为大量产品编码创建条形码的企业和用户。我们将逐步讲解从准备数据到最终生成条形码的完整过程,并提供实用的操作技巧。 ... [详细]
  • 制程能力分析:Cpk及其相关指数的深入探讨
    本文详细介绍了制程能力指数(Cpk)的概念及其与Cp、Pp、Ppk之间的关系,通过具体案例和图表展示如何评估和改进生产过程的能力。文章还提供了使用Excel和Minitab进行批量计算的实际操作步骤。 ... [详细]
  • 如何使用PyCharm及常用配置详解
    对于一枚pycharm工具的使用新手,正确了解这门工具的配置及其使用,在使用过程中遇到的很多问题也可以迎刃而解,文中有非常详细的介绍, ... [详细]
  • 本文介绍了MindManager在项目管理中的强大功能,特别是其内置的甘特图工具。通过该工具,用户可以轻松创建和管理项目计划,优化任务分配,并与其他软件无缝集成。 ... [详细]
  • 简化报表生成:EasyReport工具的全面解析
    本文详细介绍了EasyReport,一个易于使用的开源Web报表工具。该工具支持Hadoop、HBase及多种关系型数据库,能够将SQL查询结果转换为HTML表格,并提供Excel导出、图表显示和表头冻结等功能。 ... [详细]
  • 鼠标悬停出现提示信息怎么做
    概述–提示:指启示,提起注意或给予提醒和解释。在excel中会经常用到给某个格子增加提醒信息,比如金额提示输入数值或最大长度值等等。设置方式也有多种,简单的,仅为单元格插入批注就可 ... [详细]
  • ABBYY FineReader:高效PDF转换、精准OCR识别与文档对比工具
    在处理PDF转换和OCR识别时,您是否遇到过格式混乱、识别率低或图表无法正常识别的问题?ABBYY FineReader以其强大的功能和高精度的识别技术,完美解决这些问题,帮助您轻松找到最终版文档。 ... [详细]
  • 1.执行sqlsever存储过程,消息:SQLServer阻止了对组件“AdHocDistributedQueries”的STATEMENT“OpenRowsetOpenDatas ... [详细]
author-avatar
悶得咪_438
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有