Mirror的多人连接管理及房间系统

以下是一个基于Mirror的多人连接管理及房间系统的服务端实现方案,包含部署说明:

一、服务端架构设计

  1. 网络管理扩展

    using Mirror;
    using UnityEngine;

    public class RoomNetworkManager : NetworkManager
    {
    // 房间字典(房间ID -> 房间对象)
    public static Dictionary<string, Room> rooms = new Dictionary<string, Room>();

    复制代码
     public override void OnServerConnect(NetworkConnection conn)
     {
         base.OnServerConnect(conn);
         Debug.Log($"客户端 {conn.connectionId} 已连接");
     }
    
     public override void OnServerDisconnect(NetworkConnection conn)
     {
         // 处理玩家断开逻辑
         var player = conn.identity.GetComponent<NetworkPlayer>();
         if (player != null && player.CurrentRoom != null)
         {
             player.CurrentRoom.RemovePlayer(player);
         }
         
         base.OnServerDisconnect(conn);
         Debug.Log($"客户端 {conn.connectionId} 已断开");
     }

    }

复制代码
  1. 房间类实现

    public class Room
    {
    public string RoomID { get; } = Guid.NewGuid().ToString().Substring(0, 8);
    public string RoomName { get; set; }
    public int MaxPlayers { get; } = 4;
    public bool IsPlaying { get; set; }

    复制代码
     public List<NetworkPlayer> Players { get; } = new List<NetworkPlayer>();
     public NetworkPlayer Host => Players.FirstOrDefault();
    
     public bool AddPlayer(NetworkPlayer player)
     {
         if (Players.Count >= MaxPlayers || IsPlaying) return false;
         
         Players.Add(player);
         player.CurrentRoom = this;
         player.RpcJoinRoomSuccess(RoomID);
         UpdateAllPlayers();
         return true;
     }
    
     public void RemovePlayer(NetworkPlayer player)
     {
         Players.Remove(player);
         player.CurrentRoom = null;
         UpdateAllPlayers();
         
         if (Players.Count == 0)
         {
             RoomNetworkManager.rooms.Remove(RoomID);
         }
     }
    
     private void UpdateAllPlayers()
     {
         foreach (var p in Players)
         {
             p.RpcUpdateRoomInfo(GetRoomInfo());
         }
     }
    
     public RoomInfo GetRoomInfo() => new RoomInfo
     {
         roomId = RoomID,
         playerCount = Players.Count,
         hostName = Host?.PlayerName
     };

    }

复制代码
  1. 玩家网络对象

    public class NetworkPlayer : NetworkBehaviour
    {
    [SyncVar] public string PlayerName;
    [SyncVar] public bool IsReady;
    public Room CurrentRoom;

    复制代码
     [Command]
     public void CmdCreateRoom(string roomName)
     {
         Room newRoom = new Room { RoomName = roomName };
         RoomNetworkManager.rooms.Add(newRoom.RoomID, newRoom);
         newRoom.AddPlayer(this);
     }
    
     [Command]
     public void CmdJoinRoom(string roomId)
     {
         if (RoomNetworkManager.rooms.TryGetValue(roomId, out Room room))
         {
             if (!room.AddPlayer(this))
             {
                 TargetJoinRoomFailed("房间已满或游戏已开始");
             }
         }
         else
         {
             TargetJoinRoomFailed("房间不存在");
         }
     }
    
     [TargetRpc]
     public void TargetJoinRoomFailed(string reason) { /* 客户端处理 */ }
    
     [Command]
     public void CmdStartGame()
     {
         if (CurrentRoom.Host != this) return;
         CurrentRoom.IsPlaying = true;
         ServerChangeScene("GameScene");
     }

    }

复制代码

二、部署流程

  1. 服务器构建

    使用Headless模式构建Linux服务器

    Unity.exe -batchmode -nographics -buildTarget Linux64 -buildPath ServerBuild -quit

复制代码
  1. 服务器配置

    // NetworkManager配置
    public class ServerConfig : MonoBehaviour
    {
    void Start()
    {
    // 设置服务器参数
    Transport.activeTransport = GetComponent<TelepathyTransport>();
    GetComponent<RoomNetworkManager>().networkAddress = "0.0.0.0";
    GetComponent<RoomNetworkManager>().StartServer();
    }
    }

复制代码
  1. **网络要求
  • 开放端口:7777(默认TCP/UDP)

  • 建议使用固定公网IP或DDNS

  • 推荐服务器配置:

    • 最低:2核CPU / 4GB RAM(支持50人同时在线)

    • 推荐:4核CPU / 8GB RAM(支持200人同时在线)

三、客户端交互示例

  1. 创建房间

    public void CreateRoom(string roomName)
    {
    NetworkClient.localPlayer.GetComponent<NetworkPlayer>().CmdCreateRoom(roomName);
    }

复制代码
  1. 加入房间

    public void JoinRoom(string roomId)
    {
    NetworkClient.localPlayer.GetComponent<NetworkPlayer>().CmdJoinRoom(roomId);
    }

复制代码

四、优化建议

  1. 心跳检测

    // 添加心跳机制防止假连接
    [System.Serializable]
    public class HeartbeatConfig
    {
    public float Interval = 5f;
    public float Timeout = 15f;
    }

复制代码
  1. 房间清理

    void CleanEmptyRooms()
    {
    var emptyRooms = rooms.Values.Where(r => r.Players.Count == 0).ToList();
    foreach (var room in emptyRooms)
    {
    rooms.Remove(room.RoomID);
    }
    }

复制代码

五、安全措施

  1. 数据验证

    [Command]
    public void CmdSendChat(string message)
    {
    // 防止注入攻击
    if (message.Length > 100) return;
    if (message.Contains("<script>")) return;

    复制代码
     RpcReceiveChat(PlayerName, message);

    }

复制代码
  1. 频率限制

    Dictionary<NetworkConnection, float> lastCommandTimes = new Dictionary<NetworkConnection, float>();

    bool CheckRateLimit(NetworkConnection conn)
    {
    if (lastCommandTimes.TryGetValue(conn, out float lastTime))
    {
    if (Time.time - lastTime < 0.5f) return false;
    }
    lastCommandTimes[conn] = Time.time;
    return true;
    }

复制代码

该方案实现了完整的房间管理功能,支持:创建房间、自动房间ID生成、玩家数量限制、游戏状态管理、断线处理等核心功能。部署时需根据实际并发量调整服务器配置,建议配合数据库实现持久化存储。

相关推荐
越甲八千2 小时前
windowsC++操作ADB
c++·windows·adb
一个懒鬼3 小时前
Edge浏览器打开PDF文件显示空白(每次需要等上一会)
windows·pdf
com未来5 小时前
使用 NSSM 安装 Tomcat 11.0.6 为 Windows 服务
java·windows·tomcat
不要数手指啦6 小时前
Apifox使用方法
windows
IT专业服务商16 小时前
联想 SR550 服务器,配置 RAID 5教程!
运维·服务器·windows·microsoft·硬件架构
海尔辛16 小时前
学习黑客5 分钟小白弄懂Windows Desktop GUI
windows·学习
gushansanren16 小时前
基于WSL用MSVC编译ffmpeg7.1
windows·ffmpeg
伐尘17 小时前
【Qt】编译 Qt 5.15.x For Windows 基础教程 Visual Studio 2019 MSVC142 x64
windows·qt·visual studio
专注代码七年17 小时前
在Windows 境下,将Redis和Nginx注册为服务。
windows·redis·nginx