MQTT学习(四)--使用m2mqtt在Unity3D中实现MQTT客户端

在前面的几篇文章中分别在桌面客户端和Web客户端中实现了MQTT协议的功能,为了丰富MQTT协议的使用场景,本篇文章就来尝试如何在Unity3D中实现MQTT协议的部分功能。


1.引入m2mqtt

m2mqtt是比较流行的MQTT开源类库之一,在GitHub上可以找到专为Unity3D封装的m2mqtt库,名为Unity3D_MQTT,地址为

https://github.com/vovacooper/Unity3d_MQTT

将项目下载到本地,使用Unity3D打开,我用的版本是5.5,这个项目的版本更早,毕竟是几年前的,版本为5.0。项目中自带了一个示例脚本供参考,为了方便后面的使用,将MQTT相关文件打包输出。(去掉了不必要的场景文件和示例脚本)
在这里插入图片描述
之后使用Unity3D新建一个本地项目,导入刚刚输出的资源包。新增一个空物体命名为MainTarget做后面挂载脚本用,同时将当前场景保存为Home场景作为本项目的主场景。
在这里插入图片描述

2.页面布局

Unity3D的页面布局与WPF、HTML有所不同,WPF和HTML都是基于XML结构的标签型布局。简单起见,Uniy3D布局就使用其自带的UI系统。
首先在场景中添加一个画板Canvas,所有UI都将在画板上呈现,之后在Canvas上添加一个布局空间Panel。

注意:Unity3D默认是三维视角的,为了确保UI始终能在屏幕即主相机范围内显示,需要对Canvas属性进行修改。

设置步骤如下:

  1. 设置Canvas所在图层为“UI”
  2. 设置Canvas的Render Mode渲染模式为Screen Space-Camera
  3. 设置Render Camera为当前主相机MainCamera
    在这里插入图片描述

然后按照和前两篇文章同样的需求依次添加UI对象,最终构建出界面。
在这里插入图片描述

3.代码实现

新建一个C#脚本MainTargetScript,并将脚本附加到对象MainTarget上,主要的功能都将在MainTargetScript.cs中实现。

3.1. UI绑定

与WPF、HTML不同,Unity3D有自身一套独特的交互体系,所以在UI交互上按照Unity3D的规则来做。为了简便,此处采用的是比较原始的方法。
在MainTargetScript类中定义UI对象:

    #region UI对象
    public InputField inputIP;//IP地址输入框
    public InputField inputPort;//端口号输入框
    public Button btnConnect;//连接按钮
    public Button btnDisconnect;//断开按钮
    public Toggle togTopic1;//主题选择框
    public Toggle togTopic2;//主题选择框
    public Toggle togTopic3;//主题选择框
    public Toggle togTopic4;//主题选择框
    public Toggle togTopic5;//主题选择框
    public Button btnSubscribe;//订阅按钮
    public Text txtResult;//结果输出文本框
    public Dropdown dropTopics;//发布主题选择框
    public InputField inputContent;//发布内容
    public Button btnPublish;//发布按钮
    public GameObject target;
    #endregion

然后在Unity3D编辑器中将UI对象与脚本中的公共对象绑定。
在这里插入图片描述

3.2. UI交互事件绑定

绑定好UI控件后,在脚本MainTargetScript的Start事件中绑定按钮、下拉框等的触发事件。

    void Start () {
        btnConnect.onClick.AddListener(btnConnect_Click);
        btnDisconnect.onClick.AddListener(btnDisconnect_Click);
        btnSubscribe.onClick.AddListener(btnSubscribe_Click);
        btnPublish.onClick.AddListener(btnPublish_Click);
        dropTopics.onValueChanged.AddListener(dropTopics_ValueChange);
        togTopic1.onValueChanged.AddListener(togTopic_ValueChange);
        togTopic2.onValueChanged.AddListener(togTopic_ValueChange);
        togTopic3.onValueChanged.AddListener(togTopic_ValueChange);
        togTopic4.onValueChanged.AddListener(togTopic_ValueChange);
        togTopic5.onValueChanged.AddListener(togTopic_ValueChange);

    }

    #region 订阅主题选中事件
    private void togTopic_ValueChange(bool arg0)
    {
    } 
    #endregion

    #region 发布主题选中事件
    private void dropTopics_ValueChange(int arg0)
    {
    } 
    #endregion

    #region 发布按钮点击事件
    private void btnPublish_Click()
    {
    } 
    #endregion

    #region 订阅按钮点击事件
    private void btnSubscribe_Click()
    {
    } 
    #endregion

    #region 断开按钮点击事件
    private void btnDisconnect_Click()
    {
    } 
    #endregion

    #region 连接按钮点击事件
    private void btnConnect_Click()
    {
    }

    #endregion

3.3. MQTT功能实现

m2mqtt与之前在WPF客户端使用的MQTTNet类库均为.Net平台,所以基本用法大同小异,只是一些数据结构和方法参数不太一样。下面就直接在UI交互事件中完善相关代码:

    #region 变量
    private string[] allTopics = { "/data/alarm", "/data/message", "/data/notify", "/action/start", "/action/stop" };
    private List<string> selectedTopics;//选中订阅的主题
    private string currentTopic;//选中发布的主题
    private MqttClient client;//客户端
    #endregion

    // Use this for initialization
    void Start () {
        selectedTopics = new List<string> { "/data/alarm", "/data/message", "/data/notify", "/action/start", "/action/stop" };
        btnConnect.onClick.AddListener(btnConnect_Click);
        btnDisconnect.onClick.AddListener(btnDisconnect_Click);
        btnSubscribe.onClick.AddListener(btnSubscribe_Click);
        btnPublish.onClick.AddListener(btnPublish_Click);
        dropTopics.onValueChanged.AddListener(dropTopics_ValueChange);
        togTopic1.onValueChanged.AddListener(togTopic_ValueChange);
        togTopic2.onValueChanged.AddListener(togTopic_ValueChange);
        togTopic3.onValueChanged.AddListener(togTopic_ValueChange);
        togTopic4.onValueChanged.AddListener(togTopic_ValueChange);
        togTopic5.onValueChanged.AddListener(togTopic_ValueChange);

    }

    #region 订阅主题选中事件
    private void togTopic_ValueChange(bool arg0)
    {
    	//获取当前选中的对象
        var current = UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject;
        string topic = current.GetComponentInChildren<Text>().text;
        if (arg0)//选中
        {
            selectedTopics.Add(topic);
        }
        else//未选中
        {
            selectedTopics.Remove(topic);
        }
    } 
    #endregion

    #region 发布主题选中事件
    private void dropTopics_ValueChange(int arg0)
    {
        currentTopic = allTopics[arg0];
    } 
    #endregion
    // Update is called once per frame
    void Update () {
		
	}
    #region 发布按钮点击事件
    private void btnPublish_Click()
    {
        string content = inputContent.text;
        if (client!=null&&!string.IsNullOrEmpty(currentTopic)&&!string.IsNullOrEmpty(content))
        {
            client.Publish(currentTopic, System.Text.Encoding.UTF8.GetBytes(content), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, true);
        }
    } 
    #endregion

    #region 订阅按钮点击事件
    private void btnSubscribe_Click()
    {
        if (client!=null&&selectedTopics!=null)
        {
            client.Subscribe(selectedTopics.ToArry(), new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
        }
    } 
    #endregion

    #region 断开按钮点击事件
    private void btnDisconnect_Click()
    {
        if (client!=null)
        {
            client.Disconnect();
        }
    } 
    #endregion

    #region 连接按钮点击事件
    private void btnConnect_Click()
    {
        string txtIP = inputIP.text;
        string txtPort = inputPort.text;
        string clientId = Guid.NewGuid().ToString();
        string username = "admin";
        string password = "password";
        //客户端实例化
        client = new MqttClient(IPAddress.Parse(txtIP), int.Parse(txtPort),false,null);
        //绑定接收事件
        client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
        //连接服务端
        client.Connect(clientId, username, password);
    }

    //接收到发布的消息
    private void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
    {
        Debug.Log("Topic:"+e.Topic);
        string tmp = System.Text.Encoding.UTF8.GetString(e.Message);
        Debug.Log("Message" + tmp);
        txtResult.text=tmp;
    }
    #endregion

代码编写完成后打包发布成exe程序。

4.测试实例

这次测试分别打开一个Unity3D客户端、一个WPF客户端、一个Web客户端。同样还是打开Apollo的管理界面查看结果。

分别连接,服务端管理界面上可以查到tcp模式有两个终端,ws(WebSocket)模式有一个。连接功能正常。
在这里插入图片描述

再测试下订阅、发布功能。订阅相应主题的能收到,没有订阅相应主题的就收不到。

在这里插入图片描述

大功告成,至此在Unity3D上实现MQTT协议就完成了。


勤能补拙,不断试错。

源代码地址

  • 8
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 31
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值