Unity Mirror 之 NetworkDiscovery原理

755 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情

在局域网联机游戏时,需要知道Host主机的IP地址,然后客户端通过IP地址连接到服务器。但作为游戏来说,让用户输入IP地址不是特别人性化,因此Mirror提供了一个NetworkDiscoverty组件,可以发现局域网上已经建立的游戏。本文中会总结一下Network Discovery的原理。

Network Discovery原理

Mirror主机开始游戏后,其他玩家怎么知道有这个主机存在?实际上是不会知道的。要想知道必须主机启动一个服务,等着玩家客户端去发现。在Mirror中,Network Discovery是通过主机登记自己实现,即NetworkDiscoveryBaseAdvertiseServer方法。这个方法内部,会启动一个UDP client,这client会等着客户端的NetworkDiscovery发送UDP包过来,如果它接受到来自客户端的UDP包,就会发送应答包,这样客户端就会找到这个服务器。可以看到,这就是一个简单的UDP应答机制。其实Host可以不用进入游戏,即不必启动游戏Server,它只要登记自己,启动UDP Client,就可以对所有人宣告自己的存在。对于所有人在房间中集合,然后一起开始的游戏类型,这个UDP Client就相当于一个房间的主机,等着其他人发现自己并连接进来,然后所有人准备好后再启动游戏Server,并且大家一起Connect这个Server。当然这需要进一步的开发,因为Mirror提供的机制非常简单。

客户端UDP广播寻找主机

上面说服务器启动一个UDP Client等着客户端去发现,而客户端需要寻找所有可能的主机,所以它需要发送UDP广播。在Mirror中,是通过networkDiscovery.StartDiscovery方法。这个方法中,会首先创建一个UDP Client,等着接受服务器的应答包,但是服务器只有先收到UDP握手包才会发送应答包。因此StartDiscovery方法中接着就是发送广播包去寻找服务器,并且广播包会定时不断的发送,因为有可能会有新的服务器出现。

主机发现的回调

当客户端的NetworkDiscovery发现主机后,就会回调一个注册好的事件,即void OnDiscoveredServer(ServerResponse info)。注意,这只是一个主机应答的回调,由于广播包是不断发送的,因此主机会不断发送应答包,所以对同一个主机,这个回调也会不断被调用。如果存在多个主机,这个回调也会多次调用。而你的大厅程序就需要区分这些主机,哪些是新加入的,哪些是已经有的。需要注意的是,如果主机关闭了,并不会发送任何通知,所以为了能在UI上清除掉已经关闭的主机,需要实现一套心跳检查机制。

问题

NetworkDiscovery 实际使用时,发现有一些问题,导致默认的实现几乎不可以用。下篇中我们讲分析这些问题并且给出解决方案。