MQTT implementation in Basic Multiplayer via webGL Client

Aus hyperdramatik
Zur Navigation springen Zur Suche springen

First things first: I think there is no easy way how webGL could connect to an MQTT Broker directly, maybe there is but I could not figure one out. So the basic idea is to just let the server connect to the MQTT Broker and act as an hub. It as well relaxes the Broker traffic as well.

So the way we communicate is this webGL_Client --> Linux_Server --> MQTT_BROKER --> Linux_Server --> webGL-Client.

Bare this in mind.

So let´s start:

1. Download the MQTT Libary for Unity in this article --> MQTT in Unity

2. unzip the file

3. open up your multiplayer projekt we will work with this projekt -->Unity-Basic-Multiplayer

4. go to ASSESTS -> import packages -> custom packages and get the package from your downloaded folder under packages it might be named like unity3Dmqtt

5. in your assests folder you now should have a MQTT folder open it up and go to the test folder

6. delete the testMqtt script

7. make a new C# script and call it exactly -> MQTT_Debug

8. delete everything and copy this sourcecode in to your new script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MQTT_Debug : Mirror.NetworkBehaviour
{
    [
       Header("YOU NEED TO HAVE IT ON A EMPTY GAMEOBJECT", order = 0), Space(-10, order = 1),
        Header("NAMED --> MQTT", order = 2), Space(-10, order = 3),

        Space(15, order = 4),
   ]


    [Mirror.SyncVar]
    public string text; //stores incoming MQTT messages without topic if you want to sort this do it in mqttShiftIO

    [Mirror.SyncVar]
    public string msg; //stores outgoing MQTT messages

    [Mirror.SyncVar]
    public string topic; //stores outgoing MQTT topic the message is send to

}

9. save the script 10. create another one with the name -> mqttShiftrIO

using UnityEngine;
using System;
using System.Net;
using System.Collections;
using System.Collections.Generic;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using uPLibrary.Networking.M2Mqtt.Utility;
using uPLibrary.Networking.M2Mqtt.Exceptions;



public class mqttShiftrIO : Mirror.NetworkBehaviour //it inherids from Networkbehavior so we can just do it on the server - because this does not work with webGL in this setup

{
	private MqttClient client;
	
	const string glyphs = "abcdefghijklmnopqrstuvwxyz0123456789"; // this is for creating a random Client_ID
	int charAmount; // this is for creating a random Client_ID

	// Use this for initialization
	public string Shiftrio_ClientID = "MyNameOnShiftIoIwant";
	public string Shiftrio_Key = "key findest du im token";
	public string Shiftrio_Secret = "langeNummer findest du unter secret im token";

	
	public string msg = "";
	
	public string sendMsg = "";
	private string sendMsgOld = "";

	public string sendTopic = "";
	private string sendTopicOld = "";

	public MQTT_Debug debug;

	public List<string> topics_sub = new List<string>();

	
	void Start () {
		// create client instance
		client = new MqttClient(IPAddress.Parse("34.76.6.166"), 1883 , false , null ); // IPAddress.Parse("34.76.6.166") --> this is just the ip adress of broker.shiftr.io //
		// if you want to use another broker change it it could read http addresses as string as well or if you use a local ip you could use this as well
		//1883 is the commen port for MQTT shiftr.io uses a 8883 as secure port check the documentation

		// register to message received 
		client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
		
		charAmount = UnityEngine.Random.Range(3, 8);									// this is for creating a random Client_ID
		for (int i = 0; i < charAmount; i++)                                            // this is for creating a random Client_ID
		{                                                                               // this is for creating a random Client_ID
			Shiftrio_ClientID += glyphs[UnityEngine.Random.Range(0, glyphs.Length)];    // this is for creating a random Client_ID
		}                                                                               // this is for creating a random Client_ID

		client.Connect(Shiftrio_ClientID, Shiftrio_Key, Shiftrio_Secret); // connecting Unity to Shiftr.IO broker if you use Broker without username and password use only the clientID 
		
		// subscribe to the topics in topics_sub list with QoS 2 
		foreach (String topic in topics_sub) {
			client.Subscribe(new string[] { topic }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
		}
		

	}
	
	void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e) 
	{
		string topic = e.Topic; //the topic of incoming message
		msg = System.Text.Encoding.UTF8.GetString(e.Message);
		Debug.Log("Received: " + topic +" --> "+ msg);
		debug.text = msg; //the value of the incoming topic
		
	}

	void Update()
    {
		sendMsg = debug.msg; //gets msg from MQTT_Debug object
		sendTopic = debug.topic; //gets topic from MQTT_Debug object

		if (!sendMsg.Equals(sendMsgOld) || !sendTopic.Equals(sendTopicOld)) // checks if 
		{
			client.Publish(sendTopic, System.Text.Encoding.UTF8.GetBytes(sendMsg), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, true); //sends the message to topic in QoS 2 and retain mode
			sendMsgOld = sendMsg; //makes new message looking old
			sendTopicOld = sendTopic; //makes new message looking old
		} 
    }

	void OnApplicationQuit() //this should end the connection to the MQTT broker but it somehow didn´t
	{
		client.Disconnect();
		Debug.Log("MQTT Client disconnect");
	}


}

11. save save save

12. now we have to change an existing script to be able to call commands later on. so search for the PlayerData script and open it up

13. put the following code somewhere in the script maybe after the RpcTalk Command

//MQTT//////////////we just change the values in the MQTT debug object but we need to do this from the localplayer because he has Authority to change it on the server

    [Mirror.Command] //you need a MQTT Gameobject in order to use this on this Gamobject you need a MQTT_Debug.cs script and a networkidentity
    public void CmdSendMsgToServer(string newMsg, string newTopic)
    {
        GameObject.Find("MQTT").GetComponent<MQTT_Debug>().msg = newMsg;
        GameObject.Find("MQTT").GetComponent<MQTT_Debug>().topic = newTopic;
        RpcSendToMsg(newMsg, newTopic);
    }

    [Mirror.ClientRpc] //here we change it for the clients to that everyone is up to date which MQTT message was last sended 
    public void RpcSendToMsg(string myMsg, string newTopic)
    {
        GameObject.Find("MQTT").GetComponent<MQTT_Debug>().msg = myMsg;
        GameObject.Find("MQTT").GetComponent<MQTT_Debug>().topic = newTopic;
    }

    //NOT//MQTT//////////////

14. create a Gameobject named exactly MQTT and put on this object the MQTT_Debug script

15. create another GameObject and name it as you like mine is called shiftrIO put on the mqttShiftrIO script

16. if everything worked out is should now as well have a NetworkIdentity please check the Server Only box

17. now drag the MQTT GameObject into the Debug variable on the script in the inspector to connect both scripts

18. fill in your shiftr.io credentials

19. so if you hit the