在前面的文章中写过如何搭建SignalR服务端和客户端,也写过如何将Unity3D应用嵌入到WPF中,问题是SignalR服务端和WPF客户端实时通信很简单,SignalR服务端怎么与Unity3D应用实时传输数据呢?下面就开始讨论了。


1.问题背景

1.1为什么要在Unity3D中实时传输数据?

在多人游戏中要实时显示对手的数据,如位置、血量等。在3D业务系统中可能要显示外部提供的一些数据,而这些数据是随时都有可能发生变化的,需要实时在Unity3D应用中显示出来,比如外部采集的温度、湿度等。

1.2为什么要使用SignalR进行实时通信?

选用SignalR进行实时通信并不意味着在Unity3D中进行实时通信只有SignalR这一种方案,只是在之前的文章中使用融合SignalR的WebAPI做服务端已经很顺手了,业务系统也相对成熟,所以打算继续沿用下去。目前常见的方案一般是用Socket做通信,但是需要自己做底层的封装,对于我这种技术菜鸟而言搞不定,所以最终还是希望能够使用SignalR做实时数据传输。

WebAPI集成SignalR

1.3如何将SignalR应用到Unity3D中?

最开始我的想法是,反正都是C#的类库,直接添加进去引用就好了。但是Unity3D编辑器是基于Mono解决方案的,而Mono是基于.Net Framework3.5的,SignalR客户端对运行环境的要求是至少是.Net Framework4.5的,这也就意味着是无法直接在Unity3D中使用SignalR的。问题似乎陷入了僵局,但是天无绝人之类,我们发现在Unity应用商店有一个神奇的插件:BestHttp,对比较常用的网络通信方式进行了封装,包括Http、WebSocket、Socket和我们很熟悉的SignalR。BestHttp比Unity3D自带的www功能丰富很多,但是请注意,BestHttp是收费的,BestHttp是收费的,BestHttp是收费的,重要事情说三遍。

2.解决方案

通过上面的分析,我们决定采用融合SignalR的WebAPI作为客户端,Unity3D融合BestHttp作为客户端,采用之前开发的OPCClient作为采集端,搭建一个实时监测温湿度等环境参数的例子。

融合SignalR的OPCClient实现环境参数实时监测

2.1安装BestHttp

打开Unity3D编辑器,新建项目MonitorDemo,选择菜单Window>Asset Store,打开应用商店查找BestHttp,导入到项目中。

导入完成后可以看到Assets目录下面多了一个BestHttp的文件夹,可以在文件夹下找到BestHttp的说明文档,本文中的例子都是基于这份说明文档进行开发的。

2.2搭建Unity3D界面

使用Unity3D的UI添加一个Canvas,添加两个Text,TextTempKey显示“温度”,TextTempValue显示温度数据。

为了看的清楚些,加了一个图片做背景。
将Canvas的Render Mode改为Screen Space-Camera,并将Render Camera改为MainCamera,使得Canvas始终以UI界面形式呈现。

2.3创建C#脚本

新建脚本SignalrHelper

public class SignalrHelper : MonoBehaviour
{public Text txt;private Connection _connection;private Hub _proxy;readonly Uri _uri=new Uri("http://localhost:49749/MessageBus");// Use this for initializationvoid Start () {//实例化代理Hub_proxy=new Hub("MessageHub");//实例化连接_connection=new Connection(_uri,_proxy);//接收数据事件注册_proxy.On("receiveData",ReceiveData);//启动连接_connection.Open();}private void ReceiveData(Hub hub, MethodCallMessage methodCall){string arg0 = methodCall.Arguments[0].ToString();ItemValueModel item = Newtonsoft.Json.JsonConvert.DeserializeObject<ItemValueModel>(arg0);Debug.Log("I received data:"+arg0);txt.text=item.value;}// Update is called once per framevoid Update () {}}void OnDestory(){if (_connection!=null){_connection.Close();}}
}

其中ItemValueModel是我们定义的监测项数据类

/// <summary>
/// 监测标签数据类
/// </summary>
public class ItemValueModel
{/// <summary>/// 标签唯一标识/// </summary>public string id { get; set; }/// <summary>/// 标签名称/// </summary>public string name { get; set; }/// <summary>/// 标签数据值/// </summary>public string value { get; set; }
}

将脚本SignalrHelper作为组件添加到Canvas上,并将所定义的Canvas的txt属性设为TextTemp_Value,使得Canvas初始化的时候就能与服务端建立连接,并监听服务端方法receiveData,当接收到数据时将TextTemp_Value的文本改为测点值。

2.4添加服务端方法

public class MessageHub:Hub
{public async Task ReceiveData(string data){ItemValueModel item = JsonConvert.DeserializeObject<ItemValueModel>(data);await Clients.All.receiveData(item);}
}

完成以上工作后,启动服务端,然后依次启动采集端(OPCClient)和客户端(Unity3D),看到跳动的数字就说明成功了。

3.方案改进

在上面的步骤已经实现了一个测点的实时数据监测,但显然有点简单了,因为实际上我们在业务系统中不可能只有一个测点,而且并不仅仅只是读取数据,还会有写入数据的情况。另外在上面的示例运行的时候发现测点数据变化频率很快的时候,界面会变得卡顿,于是针对这些问题进行改进。

3.1添加数据处理队列

    private static Queue<ItemValueModel> _queue;private void ReceiveData(Hub hub, MethodCallMessage methodCall){string arg0 = Newtonsoft.Json.JsonConvert.SerializeObject(methodCall.Arguments[0]);ItemValueModel item = Newtonsoft.Json.JsonConvert.DeserializeObject<ItemValueModel>(arg0);_queue.Enqueue(item);}

接收到测点数据变化时,并不立即处理,而是将数据添加到队列_quene中,在Update方法中去处理数据,这样处理数据就和帧刷新保持一致,避免出现卡顿的现象。

    void Update () {if (_queue.Any()){ItemValueModel item = _queue.Dequeue();string tmp = item.id.ToUpper();GameObject go = GameObject.FindWithTag(tmp);if (go != null){Debug.Log(go.name);var target = go.GetComponent<Text>();if (target != null){target.text = item.value;Debug.Log(target.name + ":" + item.value);}}}}

3.2添加数据写入方法

在脚本SignalrHelper中添加写入数据的方法,并通过BestHttp提供的Call方法发送给服务端。

    public Button button;public Text text_ID;public Text text_Value;void Start () {//数据处理队列_queue=new Queue<ItemValueModel>();//按钮事件button.onClick.AddListener(delegate(){            WriteItem(text_ID.text,text_Value.text);});//实例化代理Hub_proxy=new Hub("MessageHub");//实例化连接_connection=new Connection(_uri,_proxy);//接收数据事件注册_proxy.On("receiveData",ReceiveData);//启动连接_connection.Open();}private void WriteItem(string id,string value){if (_connection!=null&&_proxy!=null){_proxy.Call("WriteItem", id, value);}}

3.3添加界面控件

添加两个Input分别用来输入要写入的标签名称和值,添加一个Button用来发送写入命令,再多加几个Text来表示不同的标签。

通过以上的改造我们就能在Unity3D中实现多个测点实时数据的监测和测点数据写入了,也就意味着如果是一个设备监控系统的话,我们就能在Uinity3D里进行设备状态的监测和控制了。


在上面的步骤中,我们使用BestHttp在Unity3D里与SignalR服务端建立连接,实现了实时通信,但仍有部分问题需要解决:
如何将将SignalrHelper作为实时通信的总入口,实现数据传输的模块化?
如何实现测点数据与UI控件的动态绑定?
这些问题也许会在后面的实践中得到解决。

Unity3D+SignalR实现实时数据传输相关推荐

  1. matlab实时数据传输,利用QuaRC实现c++与simulink(matlab)之间实时双向数据传输

    1. 软件环境 1.1 Visual Studio 2005/2008/2010/2012(楼主用的2012) 1.2 Matlab (楼主用的2013b) 1.3 QuaRC  (楼主用的2.4版本 ...

  2. [Asp.net]SignalR实现实时日志监控

    摘要 昨天吃饭的时候,突然想起来一个好玩的事,如果能有个页面可以实时的监控网站或者其他类型的程序的日志,其实也不错.当然,网上也有很多成熟的类似的监控系统.就想着如果通过.net该如何实现?所以就在想 ...

  3. C# ASP.NET MVC 之 SignalR 学习 实时数据推送显示 配合 Echarts 推送实时图表

    本文主要是我在刚开始学习 SignalR 的技术总结,网上找的学习方法和例子大多只是翻译了官方给的一个例子,并没有给出其他一些经典情况的示例,所以才有了本文总结,我在实现推送简单的数据后,就想到了如何 ...

  4. MVC SignalR Hub实时聊天实时Web解决方案

    目录 介绍 背景 1. WebSocket 2.服务器发送事件(SSE) 3.永远的Frame 4.轮询 5.长轮询 场景描述 先决条件 使用代码 第1步:创建项目 步骤2:打开PM以安装依赖项文件 ...

  5. ASP.NET Core 使用SignalR后台实时推送数据给Echarts展示图表

    什么是 SignalR ASP.NET Core ASP.NET Core SignalR 是一种开放源代码库,可简化将实时 web 功能添加到应用程序的功能. 实时 web 功能使服务器端代码可以立 ...

  6. Unity3d游戏画面实时同步html5或WebGL中(基于FMETP STREAM)

    一.准备画面发送端 1.新建unity3d工程(这里的版本为Unity3d2018.4.14),导入FMETP STREAM插件. 2.在场景创建空实体FMSocketIOManager,添加FMSo ...

  7. 面对大量的实时数据传输代替HTTP采用的TCP长连接的方案

    一.为什么要采用长连接 要弄清楚这个问题,我们先来看一看TCP连接建立的一些过程. 建立连接三次握手,断开连接四次挥手,如图: 慢启动 最初的TCP的实现方式是,在连接建立成功后便会向网络中发送大尺寸 ...

  8. 【Unity3D】2018实时渲染电影短片《死者之书》技术文章合集

    本篇文章首发于作者个人博客,原链:https://www.huozk.com/2018/unity3d-bookofthedead.html 古埃及人相信,人死后要先经历一段去往冥国的旅程,通过各种考 ...

  9. SignalR网页实时推送

    1.新建项目,选择mvc4 Wed应用程序,选择Internet,视图引擎:Razor 2.在控制器中添加 并添加上视图 3.引用(install-package Microsoft.AspNet.S ...

最新文章

  1. activemq的学习,第一篇
  2. 【Python基础】Python处理文件的几个常用小知识
  3. ABAP开发者上云的时候到了 - 现在大家可以免费使用SAP云平台ABAP环境的试用版了
  4. python函数参数传递机制_Python 学习笔记(一) 理解Python的函数传参机制
  5. 实现在线用户列表的简单方法
  6. java解析xml串标签_Java反射解析XML字符串并封装到指定的JavaBean
  7. sqlserver CASE WHEN语句示例
  8. http,https,spdy,http2等协议的主要区别详解
  9. 深度技术 Windows7 旗舰五周年纪念版
  10. OA项目之Mybatis多表链接查询
  11. echarts动态渲染柱状图背景颜色以及顶部数值
  12. 深度学习——损失函数(Regression Loss、Classification Loss)
  13. 7月20HashMap、集合、HashSet
  14. transparent特性
  15. 富斯,迈克,天地飞4合1接收机说明书
  16. 沈阳市举行盛大剪纸节 民间艺人现场传承工艺
  17. 《图解HTTP》思维导图
  18. 云端液位数据的由来与变送器的使用
  19. LC3-仿真器的安装
  20. 让linux挂载的移动硬盘具有执行权限

热门文章

  1. 2022“华为杯”(E、F题)思路分析、代码......
  2. 安全架构--9--企业安全开发体系建设总结
  3. 用大数据的眼光看师姐移民报告
  4. Oracle alter table
  5. WIN11 安卓子系统无法启动解决办法 无法启动适用于 Android 的 Windows 子系统 确保在可选的Windows功能中启用虚拟机平台
  6. Excel在计算机中的应用,计算机在化学中的应用 主要由excel处理.pdf
  7. 冷凝器胶球自动在线清洗装置
  8. 为啥总感觉前端有时候学不懂,想努力学又学不进去?
  9. 电脑录屏怎么把声音录进去,两招教你把声音录进去
  10. 爬虫软件 八爪鱼 使用经验