Unity3D+SignalR实现实时数据传输
在前面的文章中写过如何搭建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实现实时数据传输相关推荐
- matlab实时数据传输,利用QuaRC实现c++与simulink(matlab)之间实时双向数据传输
1. 软件环境 1.1 Visual Studio 2005/2008/2010/2012(楼主用的2012) 1.2 Matlab (楼主用的2013b) 1.3 QuaRC (楼主用的2.4版本 ...
- [Asp.net]SignalR实现实时日志监控
摘要 昨天吃饭的时候,突然想起来一个好玩的事,如果能有个页面可以实时的监控网站或者其他类型的程序的日志,其实也不错.当然,网上也有很多成熟的类似的监控系统.就想着如果通过.net该如何实现?所以就在想 ...
- C# ASP.NET MVC 之 SignalR 学习 实时数据推送显示 配合 Echarts 推送实时图表
本文主要是我在刚开始学习 SignalR 的技术总结,网上找的学习方法和例子大多只是翻译了官方给的一个例子,并没有给出其他一些经典情况的示例,所以才有了本文总结,我在实现推送简单的数据后,就想到了如何 ...
- MVC SignalR Hub实时聊天实时Web解决方案
目录 介绍 背景 1. WebSocket 2.服务器发送事件(SSE) 3.永远的Frame 4.轮询 5.长轮询 场景描述 先决条件 使用代码 第1步:创建项目 步骤2:打开PM以安装依赖项文件 ...
- ASP.NET Core 使用SignalR后台实时推送数据给Echarts展示图表
什么是 SignalR ASP.NET Core ASP.NET Core SignalR 是一种开放源代码库,可简化将实时 web 功能添加到应用程序的功能. 实时 web 功能使服务器端代码可以立 ...
- Unity3d游戏画面实时同步html5或WebGL中(基于FMETP STREAM)
一.准备画面发送端 1.新建unity3d工程(这里的版本为Unity3d2018.4.14),导入FMETP STREAM插件. 2.在场景创建空实体FMSocketIOManager,添加FMSo ...
- 面对大量的实时数据传输代替HTTP采用的TCP长连接的方案
一.为什么要采用长连接 要弄清楚这个问题,我们先来看一看TCP连接建立的一些过程. 建立连接三次握手,断开连接四次挥手,如图: 慢启动 最初的TCP的实现方式是,在连接建立成功后便会向网络中发送大尺寸 ...
- 【Unity3D】2018实时渲染电影短片《死者之书》技术文章合集
本篇文章首发于作者个人博客,原链:https://www.huozk.com/2018/unity3d-bookofthedead.html 古埃及人相信,人死后要先经历一段去往冥国的旅程,通过各种考 ...
- SignalR网页实时推送
1.新建项目,选择mvc4 Wed应用程序,选择Internet,视图引擎:Razor 2.在控制器中添加 并添加上视图 3.引用(install-package Microsoft.AspNet.S ...
最新文章
- activemq的学习,第一篇
- 【Python基础】Python处理文件的几个常用小知识
- ABAP开发者上云的时候到了 - 现在大家可以免费使用SAP云平台ABAP环境的试用版了
- python函数参数传递机制_Python 学习笔记(一) 理解Python的函数传参机制
- 实现在线用户列表的简单方法
- java解析xml串标签_Java反射解析XML字符串并封装到指定的JavaBean
- sqlserver CASE WHEN语句示例
- http,https,spdy,http2等协议的主要区别详解
- 深度技术 Windows7 旗舰五周年纪念版
- OA项目之Mybatis多表链接查询
- echarts动态渲染柱状图背景颜色以及顶部数值
- 深度学习——损失函数(Regression Loss、Classification Loss)
- 7月20HashMap、集合、HashSet
- transparent特性
- 富斯,迈克,天地飞4合1接收机说明书
- 沈阳市举行盛大剪纸节 民间艺人现场传承工艺
- 《图解HTTP》思维导图
- 云端液位数据的由来与变送器的使用
- LC3-仿真器的安装
- 让linux挂载的移动硬盘具有执行权限
热门文章
- 2022“华为杯”(E、F题)思路分析、代码......
- 安全架构--9--企业安全开发体系建设总结
- 用大数据的眼光看师姐移民报告
- Oracle alter table
- WIN11 安卓子系统无法启动解决办法 无法启动适用于 Android 的 Windows 子系统 确保在可选的Windows功能中启用虚拟机平台
- Excel在计算机中的应用,计算机在化学中的应用 主要由excel处理.pdf
- 冷凝器胶球自动在线清洗装置
- 为啥总感觉前端有时候学不懂,想努力学又学不进去?
- 电脑录屏怎么把声音录进去,两招教你把声音录进去
- 爬虫软件 八爪鱼 使用经验