MQTT implementation in Basic Multiplayer via webGL Client: Unterschied zwischen den Versionen

Aus hyperdramatik
Zur Navigation springen Zur Suche springen
Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
Zeile 47: Zeile 47:


}
}
</source>
9. save the script
10. create another one with the name -> mqttShiftrIO
<source lang="javascript" line start="2" highlight="4-6">
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");
}
}
</source>
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
<source lang="javascript" line start="2" highlight="4-6">
//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//////////////
</source>
</source>

Version vom 25. Mai 2020, 16:18 Uhr

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//////////////