支持Windows和Android平台,可自动重连。
1.下载MQTTnet,解压

2.将lib/net48/MQTTnet.dll放入 Unity 项目 Assets/Plugins 目录

3.在场景中创建物体,将脚本MqttMgr.cs、UnityMainThreadDispatcher.cs、MqttTest.cs添加到该物体。

cs
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;
public class MqttMgr : MonoBehaviour
{
public static MqttMgr Instance { get; private set; }
[Header("MQTT 配置")]
public string broker = "broker.hivemq.com";
public int port = 1883;
public string clientIdPrefix = "UnityClient_";
public string username = "";
public string password = "";
[Header("自动重连")]
public bool autoReconnect = true;
public int reconnectInterval = 3000;
public event Action OnConnected;
public event Action<string> OnDisconnected;
public event Action<string, string> OnMessageReceived;
public event Action<string> OnLog;
// 【新增】MQTT连接状态属性,外部直接调用:MqttMgr.Instance.isMqttConnected
public bool isMqttConnected => _mqttClient != null && _mqttClient.IsConnected;
/// <summary>
/// 是否已初始化
/// </summary>
public static bool IsInitialized => Instance != null;
private IMqttClient _mqttClient;
private CancellationTokenSource _cts;
private string _clientId;
private bool _isConnecting;
private bool _manualDisconnect;
private const string MQTT_TOPIC = "yiyue/lanyi";
private const string MQTT_PUBLISH = "lanyi/yiyue";
public string MqttTopic => MQTT_TOPIC;
private void Awake()
{
if (Instance != null) { Destroy(gameObject); return; }
Instance = this;
DontDestroyOnLoad(gameObject);
_clientId = clientIdPrefix + Guid.NewGuid().ToString("N").Substring(0, 8);
}
public async Task ConnectAsync()
{
if (_isConnecting) return;
try
{
_manualDisconnect = false;
_isConnecting = true;
if (_cts != null)
{
_cts.Cancel();
_cts.Dispose();
}
_cts = new CancellationTokenSource();
if (_mqttClient != null)
{
_mqttClient.ConnectedAsync -= OnClientConnected;
_mqttClient.DisconnectedAsync -= OnClientDisconnected;
_mqttClient.ApplicationMessageReceivedAsync -= OnApplicationMessageReceived;
_mqttClient.Dispose();
_mqttClient = null;
}
var factory = new MqttFactory();
_mqttClient = factory.CreateMqttClient();
var options = new MqttClientOptionsBuilder()
.WithTcpServer(broker, port)
.WithClientId(_clientId)
.WithCleanSession()
.WithKeepAlivePeriod(TimeSpan.FromSeconds(10))
.Build();
_mqttClient.ConnectedAsync += OnClientConnected;
_mqttClient.DisconnectedAsync += OnClientDisconnected;
_mqttClient.ApplicationMessageReceivedAsync += OnApplicationMessageReceived;
// 5秒超时保护,防止断网卡死
var connectTask = _mqttClient.ConnectAsync(options, _cts.Token);
var timeoutTask = Task.Delay(5000, _cts.Token);
await Task.WhenAny(connectTask, timeoutTask);
if (!connectTask.IsCompletedSuccessfully)
{
_cts.Cancel();
Log("连接超时,继续重试...");
}
}
catch (Exception ex)
{
Log($"连接异常:{ex.Message}");
}
finally
{
_isConnecting = false;
// 失败就继续重连 → 无限循环
if (!_manualDisconnect && autoReconnect && (_mqttClient == null || !_mqttClient.IsConnected))
{
_ = TryReconnectAsync();
}
}
}
public void SetBrokerAddress(string brokerIp)
{
if (string.IsNullOrWhiteSpace(brokerIp))
return;
broker = brokerIp;
}
public void SetBrokerPort(string bport)
{
if (string.IsNullOrWhiteSpace(bport))
return;
int.TryParse(bport, out port);
}
private Task OnClientConnected(MqttClientConnectedEventArgs args)
{
OnMainThread(() =>
{
Log("✅ MQTT 已连接");
OnConnected?.Invoke();
if(OnConnected != null)
Log("OnConnected not null");
else
Log("OnConnected is null");
});
return Task.CompletedTask;
}
private async Task OnClientDisconnected(MqttClientDisconnectedEventArgs args)
{
OnMainThread(() =>
{
Log($"❌ 断开:{args.Reason}");
OnDisconnected?.Invoke(args.Reason.ToString());
});
if (_manualDisconnect || !autoReconnect)
return;
await TryReconnectAsync();
}
private Task OnApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs args)
{
var topic = args.ApplicationMessage.Topic;
var payload = Encoding.UTF8.GetString(args.ApplicationMessage.PayloadSegment);
OnMainThread(() => OnMessageReceived?.Invoke(topic, payload));
return Task.CompletedTask;
}
// 无限重连核心
private async Task TryReconnectAsync()
{
if (_isConnecting) return;
Log($"⏳ {reconnectInterval / 1000} 秒后自动重试...");
await Task.Delay(reconnectInterval);
if (!_manualDisconnect && autoReconnect)
{
await ConnectAsync();
}
}
public async Task DisconnectAsync()
{
_manualDisconnect = true;
try
{
if (_cts != null)
{
_cts.Cancel();
_cts.Dispose();
_cts = null;
}
if (_mqttClient != null)
await _mqttClient.DisconnectAsync();
}
catch { }
}
public async Task SubscribeAsync(string topic, MqttQualityOfServiceLevel qos = MqttQualityOfServiceLevel.AtMostOnce)
{
if (_mqttClient == null || !_mqttClient.IsConnected) { Log("未连接"); return; }
try { await _mqttClient.SubscribeAsync(topic, qos); Log($"已订阅:{topic}"); }
catch (Exception ex) { Log($"订阅失败:{ex.Message}"); }
}
public async Task PublishAsync(string topic, string payload, MqttQualityOfServiceLevel qos = MqttQualityOfServiceLevel.AtMostOnce, bool retain = false)
{
if (_mqttClient == null || !_mqttClient.IsConnected) { Log("未连接"); return; }
try
{
var msg = new MqttApplicationMessageBuilder()
.WithTopic(topic).WithPayload(payload)
.WithQualityOfServiceLevel(qos).WithRetainFlag(retain).Build();
await _mqttClient.PublishAsync(msg);
Log($"发布 [{topic}]:{payload}");
}
catch (Exception ex) { Log($"发布失败:{ex.Message}"); }
}
public async Task PublishAsync(string payload)
{
await MqttMgr.Instance.PublishAsync("lanyi/yiyue", payload);
}
private void Log(string msg) => OnMainThread(() => { Debug.Log($"[MQTT] {msg}"); OnLog?.Invoke(msg); });
private void OnMainThread(Action act) => UnityMainThreadDispatcher.Instance.Enqueue(act);
private async void OnDestroy() => await DisconnectAsync();
}
cs
using System;
using System.Collections.Generic;
using UnityEngine;
public class UnityMainThreadDispatcher : MonoBehaviour
{
public static UnityMainThreadDispatcher Instance { get; private set; }
private readonly Queue<Action> _queue = new Queue<Action>();
private void Awake()
{
if (Instance != null)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
public void Enqueue(Action action)
{
lock (_queue)
{
_queue.Enqueue(action);
}
}
private void Update()
{
lock (_queue)
{
while (_queue.Count > 0)
_queue.Dequeue()?.Invoke();
}
}
}
cs
using UnityEngine;
using UnityEngine.UI;
public class MqttTest : MonoBehaviour
{
public Text textOutput;
public Button btnClear;
async void Start()
{
btnClear.onClick.AddListener(()=>
{
textOutput.text = "";
});
// 订阅
//await MqttMgr.Instance.SubscribeAsync("yiyue/lanyi");
// 2. 连接成功后 → 自动订阅
MqttMgr.Instance.OnConnected += async () =>
{
await MqttMgr.Instance.SubscribeAsync("yiyue/lanyi");
Instance_OnLog($"订阅 yiyue/lanyi");
};
// 连接
await MqttMgr.Instance.ConnectAsync();
// 发布
await MqttMgr.Instance.PublishAsync("lanyi/yiyue", "Hello from Unity!");
// 监听消息
MqttMgr.Instance.OnMessageReceived += (topic, msg) =>
{
Debug.Log($"收到 {topic}: {msg}");
textOutput.text += $"收到 {topic}: {msg}"+"\r\n";
};
MqttMgr.Instance.OnLog += Instance_OnLog;
}
private void Instance_OnLog(string obj)
{
textOutput.text += $"{obj}" + "\r\n";
}
}