公会系统:NetworkManager.cs
```csharp
-- C# NetworkManager.cs
// 网络管理器C#实现,负责底层的网络通信
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using WebSocketSharp;
public class NetworkManager : MonoSingleton
{
private WebSocket webSocket;
private string serverUrl;
private int serverPort;
// 回调函数
public Action onConnected;
public Action onDisconnected;
public Action onMessage;
public Action onError;
// 心跳
private float heartbeatInterval = 30f;
private float lastHeartbeatTime;
private Coroutine heartbeatCoroutine;
// 重连
private bool isReconnecting = false;
private int reconnectAttempts = 0;
private int maxReconnectAttempts = 5;
// 连接状态
public bool IsConnected { get; private set; } = false;
public void Connect(string url, int port)
{
if (IsConnected)
{
Debug.LogWarning("Already connected to server");
return;
}
serverUrl = url;
serverPort = port;
string wsUrl = $"ws://{url}:{port}";
try
{
webSocket = new WebSocket(wsUrl);
webSocket.OnOpen += (sender, e) =>
{
Debug.Log("WebSocket connected");
IsConnected = true;
onConnected?.Invoke();
StartHeartbeat();
};
webSocket.OnMessage += (sender, e) =>
{
onMessage?.Invoke(e.Data);
};
webSocket.OnError += (sender, e) =>
{
Debug.LogError($"WebSocket error: {e.Message}");
onError?.Invoke(e.Message);
};
webSocket.OnClose += (sender, e) =>
{
Debug.Log("WebSocket disconnected");
IsConnected = false;
StopHeartbeat();
onDisconnected?.Invoke();
if (!isReconnecting && reconnectAttempts < maxReconnectAttempts)
{
StartCoroutine(ReconnectCoroutine());
}
};
webSocket.ConnectAsync();
}
catch (Exception ex)
{
Debug.LogError($"Connection failed: {ex.Message}");
onError?.Invoke(ex.Message);
}
}
public void Disconnect()
{
if (webSocket != null)
{
isReconnecting = false;
reconnectAttempts = 0;
webSocket.Close();
webSocket = null;
}
}
public void Send(string data)
{
if (webSocket != null && webSocket.ReadyState == WebSocketState.Open)
{
webSocket.Send(data);
}
else
{
Debug.LogWarning("Cannot send: WebSocket not connected");
}
}
public void SendHeartbeat(string data)
{
Send(data);
}
private IEnumerator ReconnectCoroutine()
{
isReconnecting = true;
reconnectAttempts++;
Debug.Log($"Reconnecting... Attempt {reconnectAttempts}/{maxReconnectAttempts}");
yield return new WaitForSeconds(3f);
if (!IsConnected && reconnectAttempts <= maxReconnectAttempts)
{
Connect(serverUrl, serverPort);
}
else
{
isReconnecting = false;
}
}
private void StartHeartbeat()
{
StopHeartbeat();
heartbeatCoroutine = StartCoroutine(HeartbeatCoroutine());
}
private void StopHeartbeat()
{
if (heartbeatCoroutine != null)
{
StopCoroutine(heartbeatCoroutine);
heartbeatCoroutine = null;
}
}
private IEnumerator HeartbeatCoroutine()
{
while (IsConnected)
{
yield return new WaitForSeconds(heartbeatInterval);
if (IsConnected)
{
var heartbeat = new
{
type = "heartbeat",
timestamp = Time.time
};
string json = JsonUtility.ToJson(heartbeat);
webSocket.Send(json);
}
}
}
private void OnDestroy()
{
Disconnect();
}
}
```