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生成、玩家数量限制、游戏状态管理、断线处理等核心功能。部署时需根据实际并发量调整服务器配置,建议配合数据库实现持久化存储。

相关推荐
码农水水11 小时前
中国邮政Java面试:热点Key的探测和本地缓存方案
java·开发语言·windows·缓存·面试·职场和发展·kafka
沫离痕13 小时前
windows安装docker实例
windows·docker·容器
桌面运维家14 小时前
vDisk VOI架构IO瓶颈怎么办?Windows优化实战
windows·架构
非凡ghost16 小时前
MPC-QT视频播放器(基于Qt框架播放器)
开发语言·windows·qt·音视频·软件需求
ysy164806723917 小时前
Docker安装(Windows版)
windows·docker·容器
珂玥c19 小时前
windows系统nfs挂载
运维·windows·ssh·remmina·cygwin
wok15720 小时前
Windows 上使用 Docker Desktop 教程
windows·docker·容器
希赛网20 小时前
网工备考,华为ENSP基础配置命令(下)
windows·计算机网络·网络工程师·华为认证·ensp·路由交换·网工备考
马踏岛国赏樱花20 小时前
Windows与Ubuntu双系统,挂载D/E盘到Ubuntu下时只能读的问题
linux·windows·ubuntu
ulias21220 小时前
AVL树的实现
开发语言·数据结构·c++·windows