Unity插件-Mirror使用方法(十二)组件介绍(Network Discovery)

目录

一、插件介绍

二、主要组件

Network Manager

Network Manager HUD

Network Identity

Network Transform

Network Animator

Network Behaviour

Network Start Position

Network Room Manager

Network Room Player

三、Network Discovery

1、组件介绍

2、核心功能

服务器广播

客户端监听

自定义数据扩展

跨平台支持

3、关键属性与配置

4、基础使用步骤

1. 服务器端配置

2. 客户端配置

5、代码示例

1. 自定义广播数据

2. 客户端加入服务器

6、高级功能与场景

1. 密码保护房间

2. 跨局域网发现(需中继)

3. 动态端口分配

7、常见问题与解决


一、插件介绍

Unity插件-Mirror使用方法(一)Mirror介绍-优快云博客


二、主要组件

Unity插件-Mirror使用方法(二)组件介绍-优快云博客

Network Manager

Unity插件-Mirror使用方法(三)组件介绍(Network Manager)-优快云博客

Network Manager HUD

Unity插件-Mirror使用方法(四)组件介绍(​Network Manager HUD)-优快云博客

Network Identity

Unity插件-Mirror使用方法(五)组件介绍(​Network Identity)-优快云博客

Network Transform

​Unity插件-Mirror使用方法(六)组件介绍(​Network Transform)-优快云博客

Network Animator

​Unity插件-Mirror使用方法(七)组件介绍(​Network Animator)-优快云博客

Network Behaviour

​Unity插件-Mirror使用方法(八)组件介绍(​Network Behaviour)-优快云博客

Network Start Position

Unity插件-Mirror使用方法(九)组件介绍(Network Start Position)-优快云博客

Network Room Manager

Unity插件-Mirror使用方法(十)组件介绍(Network Room Manager)-优快云博客

Network Room Player

Unity插件-Mirror使用方法(十一)组件介绍(Network Room Player)-优快云博客


三、Network Discovery

1、组件介绍

Network Discovery 是 Unity Mirror 中用于局域网内自动发现服务器与客户端匹配的核心组件。它允许服务器主动广播自身的存在,而客户端则监听这些广播信息,无需手动输入IP地址即可加入游戏。非常适合局域网联机游戏(如本地多人对战、合作模式)的快速匹配。

假设你正站在朋友旁边。他启动了主机模式的游戏,而你想加入。你的手机如何定位他的游戏?直接找出他的IP地址并不直观,孩子们也很难做到。

为了解决这个问题,可以使用网络发现(Network Discovery)​。当你的游戏启动时,它会向当前网络广播一条消息:“有可用的服务器吗?”同一网络内的所有服务器都会响应,并告知如何连接到它们。

Mirror内置了一个简单的网络发现实现,你可以直接在游戏中使用。它还支持扩展功能,允许你在发现阶段传递额外数据。


2、核心功能

  1. 服务器广播

    • 服务器定期向局域网发送广播包,包含IP、端口及自定义数据(如房间名、玩家数量)。

    • 支持 UDP 协议,确保低延迟和高效率。

  2. 客户端监听

    • 客户端监听指定端口,接收局域网内的服务器广播信息。

    • 自动解析广播数据,生成可点击的服务器列表。

  3. 自定义数据扩展

    • 在广播包中添加额外信息(如游戏模式、地图名称、密码保护)。

    • 客户端根据自定义数据筛选服务器(如只显示“休闲模式”房间)。

  4. 跨平台支持

    • 兼容 Windows、Mac、Linux、Android、iOS 等主流平台。


3、关键属性与配置

属性说明
Enable Active Discovery启用客户端主动发现功能,定期发送广播请求搜索服务器
Broadcast Address广播地址(留空时默认使用局域网广播地址,如 255.255.255.255
Server Broadcast Listen Port服务器监听的UDP端口号,用于接收客户端的发现请求
Active Discovery Interval客户端主动发送发现请求的时间间隔(单位:秒)
Transport网络传输协议(需手动绑定Mirror支持的传输组件,如KCP、Telepathy等)
On Server Found (ServerResponse)发现服务器时触发的事件,需绑定自定义方法处理服务器响应(如更新UI或连接操作)

4、基础使用步骤

1. 服务器端配置

  1. 为服务器场景中的 NetworkManager 物体添加 NetworkDiscovery 组件。

  2. 勾选 Use Network Manager,确保广播端口与 NetworkManager 的端口一致。

  3. 在服务器启动代码中启用广播:

    void Start() {
        NetworkManager.singleton.StartServer();
        NetworkDiscovery.singleton.StartDiscovery();
    }

2. 客户端配置

  1. 在客户端场景中添加 NetworkDiscovery 组件。

  2. 编写监听代码并处理发现的服务器:

    public class ClientDiscovery : MonoBehaviour {
        public Transform serverListContainer;
        public GameObject serverEntryPrefab;
    
        void Start() {
            NetworkDiscovery.singleton.OnServerFound.AddListener(OnServerFound);
            NetworkDiscovery.singleton.StartDiscovery();
        }
    
        void OnServerFound(DiscoveryResponse response) {
            // 实例化服务器列表项
            GameObject entry = Instantiate(serverEntryPrefab, serverListContainer);
            entry.GetComponent<ServerEntry>().Setup(response);
        }
    }

5、代码示例

1. 自定义广播数据

using UnityEngine;
using Mirror;

// 继承自 DiscoveryRequest 和 DiscoveryResponse
public class CustomDiscovery : NetworkDiscoveryBase<DiscoveryRequest, DiscoveryResponse> {
    // 服务器发送广播数据
    protected override DiscoveryRequest GetRequest() => new DiscoveryRequest {
        gameName = "MyGame",
        playerCount = NetworkServer.connections.Count,
        mapName = "Forest"
    };

    // 客户端处理接收到的广播
    protected override void ProcessResponse(DiscoveryResponse response, IPEndPoint endpoint) {
        Debug.Log($"发现服务器: {response.gameName}, 玩家数: {response.playerCount}");
    }
}

// 自定义数据结构
[System.Serializable]
public class DiscoveryRequest {
    public string gameName;
    public int playerCount;
    public string mapName;
}

public class DiscoveryResponse : DiscoveryRequest {
    public string ipAddress;
    public int port;
}

2. 客户端加入服务器

public class ServerEntry : MonoBehaviour {
    private DiscoveryResponse serverInfo;

    public void Setup(DiscoveryResponse info) {
        serverInfo = info;
        GetComponentInChildren<Text>().text = $"{info.gameName} ({info.playerCount}/4)";
    }

    public void OnJoinButtonClick() {
        NetworkManager.singleton.networkAddress = serverInfo.ipAddress;
        NetworkManager.singleton.StartClient();
    }
}

6、高级功能与场景

1. 密码保护房间

  • 服务器广播:在广播数据中添加 hasPassword 字段。

  • 客户端筛选:仅显示无密码或输入正确密码的房间。

  • 加入验证:客户端连接后发送密码,服务器验证后允许加入。

2. 跨局域网发现(需中继)

  • 结合 NAT穿透 或 中继服务器(如 Steam Relay、Photon Cloud)实现广域网发现。

  • 示例:通过中继服务器转发广播包:

    void Start() {
        if (isServer) {
            RelayClient.SendBroadcastToRelay(serverData);
        } else {
            RelayClient.StartListening(OnRelayBroadcastReceived);
        }
    }

3. 动态端口分配

  • 避免端口冲突,允许服务器随机选择端口并广播:

    void StartServer() {
        NetworkManager.singleton.serverPort = 0; // 自动分配端口
        NetworkManager.singleton.StartServer();
        NetworkDiscovery.singleton.broadcastPort = NetworkManager.singleton.serverPort;
        NetworkDiscovery.singleton.StartDiscovery();
    }

7、常见问题与解决

问题解决方案
客户端未发现服务器检查防火墙是否放行UDP端口,确保服务器和客户端在同一局域网。
广播数据不更新确认服务器更新广播数据后重新调用 StartDiscovery()
多网卡环境失效在代码中指定广播使用的网络接口(如 NetworkDiscovery.useNetworkManager = false)。
移动端无法使用Android/iOS 需添加网络权限,确保应用有局域网访问权限。
<think>嗯,用户想了解如何在C#中实现创建房间、搜索房间和加入房间的功能。我需要先理清楚这些功能的基本逻辑,然后思考如何用C#来实现。首先,可能需要一个房间管理系统,用来管理所有的房间信息。房间的信息应该包括房间ID、名称、当前人数、最大人数、状态(比如是否公开)等等。接下来,创建房间的话,用户需要提供一个房间名称和设置一些参数,比如最大玩家数量,然后系统生成一个房间实例,并添加到房间列表中。 搜索房间可能需要根据房间名称或者房间ID来查找,或者列出所有可加入的房间。这里要考虑如何存储房间信息,可能需要一个列表或者字典来保存所有房间。加入房间的话,用户需要找到房间后,检查房间是否满员,如果没满就加入,否则提示失败。 网络通信方面,如果是本地单机的话,可能不需要网络部分,但如果是在线游戏,可能需要使用网络库,比如Unity的UNET或者Mirror,或者是TCP/UDP套接字编程。不过用户可能只是需要基本的逻辑,所以暂时不考虑网络部分,先集中在数据结构和管理逻辑上。 接下来,需要考虑房间的持久化,比如房间是否存在服务器内存中,还是需要数据库存储。这里可能先假设房间存在内存中,使用单例模式来管理房间列表。创建房间时生成唯一ID,可以用GUID或者递增的数字。搜索房间可能需要遍历房间列表,根据条件过滤。加入房间时需要线程安全,避免多个用户同时加入导致数据竞争。 另外,可能需要处理房间的销毁,比如当所有玩家离开后自动销毁房间,或者超过一定时间没有活动后销毁。不过用户的问题可能暂时不需要这些细节,所以先专注于基本功能的实现。 对于代码示例,可能需要定义一个Room类,包含房间的属性和方法,比如加入玩家、离开玩家等。再有一个RoomManager类,负责创建、搜索、销毁房间。然后给出创建房间的示例代码,搜索房间的方法,以及加入房间的流程。 需要注意线程安全,尤其是在多线程环境下操作房间列表时,可能需要使用锁机制。不过如果只是单线程或者Unity的主线程操作,可能暂时不需要考虑。但为了代码的健壮性,最好加上锁。 总结一下步骤:定义Room类 -> 创建RoomManager单例 -> 实现创建、搜索、加入方法 -> 处理并发和错误情况。然后给出示例代码,并解释每个部分的作用。可能还需要处理异常,比如房间已满,房间不存在等情况,返回相应的错误信息。 现在需要考虑用户可能的应用场景,比如是用于Unity游戏中的多人联机,还是控制台应用程序。不同的场景可能实现方式不同。比如Unity中可能需要用到Coroutine或者网络模块,而控制台应用可能更简单。但用户没有指定,所以应该给出通用的C#实现,可以在不同环境中适配。 最后,确保代码示例正确,没有语法错误,并解释关键部分,让用户能够理解如何扩展和修改。可能还需要提到如果需要网络功能,应该如何处理,比如使用Socket或WebSocket等,但根据用户的问题,可能不需要深入,只需提及即可。</think>以下是基于C#实现房间管理功能的通用方案,包含核心逻辑和代码示例: --- ### **一、基础架构设计** ```csharp // 房间数据类 public class GameRoom { public string RoomId { get; } = Guid.NewGuid().ToString(); // 唯一ID public string RoomName { get; set; } public int MaxPlayers { get; set; } = 4; public HashSet<string> Players { get; } = new(); // 玩家ID集合 public bool IsPublic { get; set; } = true; } // 房间管理器(单例模式) public class RoomManager { private static readonly Lazy<RoomManager> _instance = new(() => new RoomManager()); public static RoomManager Instance => _instance.Value; private readonly Dictionary<string, GameRoom> _rooms = new(); private readonly object _lock = new(); } ``` --- ### **二、核心功能实现** #### **1. 创建房间** ```csharp public GameRoom CreateRoom(string roomName, int maxPlayers, bool isPublic) { lock (_lock) { var room = new GameRoom { RoomName = roomName, MaxPlayers = maxPlayers, IsPublic = isPublic }; _rooms.Add(room.RoomId, room); return room; } } ``` #### **2. 搜索房间** ```csharp // 根据ID精确查找 public GameRoom FindRoomById(string roomId) { lock (_lock) { return _rooms.TryGetValue(roomId, out var room) ? room : null; } } // 根据名称模糊搜索 public List<GameRoom> SearchRooms(string keyword) { lock (_lock) { return _rooms.Values .Where(r => r.IsPublic && r.RoomName.Contains(keyword, StringComparison.OrdinalIgnoreCase)) .ToList(); } } ``` #### **3. 加入房间** ```csharp public bool JoinRoom(string roomId, string playerId) { lock (_lock) { if (!_rooms.TryGetValue(roomId, out var room)) return false; if (room.Players.Count >= room.MaxPlayers) return false; return room.Players.Add(playerId); } } ``` --- ### **三、高级功能扩展建议** 1. **房间状态维护** ```csharp // 自动清理空房间 public void CleanEmptyRooms() { lock (_lock) { var emptyRooms = _rooms.Where(kv => kv.Value.Players.Count == 0) .Select(kv => kv.Key) .ToList(); foreach (var id in emptyRooms) { _rooms.Remove(id); } } } ``` 2. **密码保护机制** ```csharp public class GameRoom { public string Password { get; set; } // 新增密码字段 } public bool JoinRoomWithPassword(string roomId, string playerId, string password) { // 验证密码逻辑... } ``` --- ### **四、使用示例** ```csharp // 创建房间 var newRoom = RoomManager.Instance.CreateRoom("战神小队", 4, true); // 搜索房间 var rooms = RoomManager.Instance.SearchRooms("战神"); // 加入房间 bool success = RoomManager.Instance.JoinRoom(newRoom.RoomId, "player_123"); ``` --- ### **五、网络集成方案** 若需要实现网络联机: 1. 使用 `Socket` 或 `WebSocket` 建立TCP连接 2. 使用 `Newtonsoft.Json` 进行消息序列化 3. 定义通信协议: ```json { "action": "join", "roomId": "xxx", "playerId": "user_001" } ``` --- 该方案可通过线程锁保证线程安全,实际部署时建议: 1. 使用数据库(如Redis)持久化房间数据 2. 添加心跳机制检测玩家离线 3. 使用消息队列处理高并发请求
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一颗橘子宣布成为星球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值