Installation
Using Unity Editor’s Package Manager window import the Best HTTP/2 package first, then Best MQTT itself. If all packages are imported properly, no further steps are required.
Initial setup
After successfully imported both the Best MQTT and Best HTTP/2 packages, you can create a new C# Script file in your Unity project and add the plugin’s namespace ‘BestMQTT
’ and ‘BestMQTT.Packets.Builders
’ somewhere around the other usings and delete the Update function as we will not going to use it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BestMQTT;
using BestMQTT.Packets.Builders;
public class MQTT : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
}
Create a new scene in Unity and assign this script to a gameobject.
Creating a ConnectionOptions instance
First we have to create a ConnectionOptions
instance to pass it to the MQTTClient
’s constructor in the next step. ConnectionOptions
contains connection related information like the Host
and Port
properties. The easiest way to create a ConnectionOptions
is using ConnectionOptionsBuilder
:
var options = new ConnectionOptionsBuilder()
.WithTCP("broker.emqx.io", 1883)
.Build();
The WithTCP("broker.emqx.io", 1883)
line tells the plugin to try to connect to the “broker.emqx.io” host with port 1883 using the TCP transport. If we want to use TLS to encrypt the server-client communication add the .WithTLS() call:
var options = new ConnectionOptionsBuilder()
.WithTCP("broker.emqx.io", 8883)
.Build();
In this guide i used EMQ X’s public broker, but there are many others to choose from.
To use Websocket as the transport protocol instead of WithTCP
the WithWebSocket
function must be used.
Creating the MQTTClient
With the newly created ConnectionOptions instance we can create the MQTTClient
instance:
var client = new MQTTClient(options);
Add general events
The client going to start to connect to the server when instructed so with BeginConnect or
ConnectAsync`. We can freely add and modify the client until one of these are called without fearing that any event is missed. Let’s add a few event handlers to catch client related events:
client.OnStateChanged += OnStateChanged;
client.OnDisconnect += OnDisconnected;
client.OnError += OnError;
And add the implementation of the event handlers:
// Called when the MQTTClient transfered to a new internal state.
private void OnStateChanged(MQTTClient client, ClientStates oldState, ClientStates newState)
{
Debug.Log($"{oldState} => {newState}");
}
// Called when the client disconnects from the server. The disconnection can be client or server initiated or because of an error.
private void OnDisconnected(MQTTClient client, DisconnectReasonCodes code, string reason)
{
Debug.Log($"OnDisconnected - code: {code}, reason: '{reason}'");
}
// Called when an error happens that the plugin can't recover from. After this event an OnDisconnected event is raised too.
private void OnError(MQTTClient client, string reason)
{
Debug.Log($"OnError reason: '{reason}'");
}
These events are not tightly related to the MQTT protocol, but they can give a good understanding when and what happens with the client connection.
A more compact way to create and setup ClientOptions
and the client itself is to use MQTTClientBuilder
:
client = new MQTTClientBuilder()
.WithOptions(new ConnectionOptionsBuilder().WithTCP("broker.emqx.io", 1883))
.WithEventHandler(OnStateChanged)
.WithEventHandler(OnDisconnected)
.WithEventHandler(OnError)
.CreateClient();
All of the event handlers have different signatures so they will be mapped to the right event.
Connecting
So far we done a basic setup of the client and added a few event handlers, but still not connected to the mqtt server. To start connecting to the server we can add a BeginConnect
call after the client setup:
client.BeginConnect(ConnectPacketBuilderCallback);
private ConnectPacketBuilder ConnectPacketBuilderCallback(MQTTClient client, ConnectPacketBuilder builder)
{
return builder;
}
BeginConnect
expects a function that returns with a connect packet builder. The builder is used to build the MQTT connect packet after the transport successfully connected to the server. Through this builder we can set up basic authentication, a will, customize negotiable values like keep alive intervals and many more. For now we can leave it as is, just returning the builder received in the second parameter.
Now we can test it and when run in Unity the Console should show something like this:
BeginConnect
and other functions starting with ‘Begin’ are non-blocking! To execute code after connected an OnConnected
event handler must be added.And disconnecting
It’s advised to disconnect when the MQTT client no longer needed. To disconnect, at a bare minimum we have to call the MQTTClient
’s CreateDisconnectPacketBuilder
, optionally call its With*
functions then finally BeginDisconnect
to send the disconnect packet to the server and let the plugin do its cleanup.
In this example we are going to set the reason code and send a nice message to the server too:
private void OnDestroy()
{
client?.CreateDisconnectPacketBuilder()
.WithReasonCode(DisconnectReasonCodes.NormalDisconnection)
.WithReasonString("Bye")
.BeginDisconnect();
}
The plugin heavily uses the builder pattern as there are a lot of optional fields that can be sent. This is the case with disconnection too. When client.CreateDisconnectPacketBuilder().BeginDisconnect()
is used it’s going to send a DisconnectReasonCodes.NormalDisconnection
without any additional data.
Now entering to and exiting from play mode in Unity should generate the following output in the console:
Final code
Putting it all together, the whole file should look like something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BestMQTT;
using BestMQTT.Packets.Builders;
public class MQTT : MonoBehaviour
{
MQTTClient client;
// Start is called before the first frame update
void Start()
{
client = new MQTTClientBuilder()
.WithOptions(new ConnectionOptionsBuilder().WithTCP("broker.emqx.io", 1883))
.WithEventHandler(OnDisconnected)
.WithEventHandler(OnStateChanged)
.WithEventHandler(OnError)
.CreateClient();
client.BeginConnect(ConnectPacketBuilderCallback);
}
private void OnDestroy()
{
client?.CreateDisconnectPacketBuilder()
.WithReasonCode(DisconnectReasonCodes.NormalDisconnection)
.WithReasonString("Bye")
.BeginDisconnect();
}
private ConnectPacketBuilder ConnectPacketBuilderCallback(MQTTClient client, ConnectPacketBuilder builder)
{
return builder;
}
private void OnStateChanged(MQTTClient client, ClientStates oldState, ClientStates newState)
{
Debug.Log($"{oldState} => {newState}");
}
private void OnDisconnected(MQTTClient client, DisconnectReasonCodes code, string reason)
{
Debug.Log($"OnDisconnected - code: {code}, reason: '{reason}'");
}
private void OnError(MQTTClient client, string reason)
{
Debug.Log($"OnError reason: '{reason}'");
}
}