概要
細かい挙動までは書きませんが、UNETを調べるとLAN対戦をするとき
- サーバIP決め打ち+NetworkManagerのみ使用
- NetworkDiscoveryでサーバを探してNetworkManagerを使う
- UNET Matching でサーバやクライアントを探してNetworkManagerを使う
の3パターンがあります。今回は真ん中の事を書きます。
あと、マジな話をするとNetworkManagerもNetworkDiscoveryも殆どのケースで継承したカスタム版を作ります。Unity標準のままで使う事は無いです。そうしないと管理できない事多過ぎです…
NetworkDiscoveryの中身
NetworkDiscoveryのサーバ側は、自分の所在(IPアドレス)をLAN内にブロードキャストパケットを流すことで宣伝して回る
NetworkDiscoveryのクライアント側は、NetworkDiscoveryのサーバが流しているブロードキャストパケットを受け取った時に専用の関数を呼ぶ
という機能だけを持っている、と覚えておきましょう。
それ以外の実際のサーバ立ち上げや、クライアント接続などは全てNetworkManager側でやります。
NetworkDiscoveryのサーバ側でプログラマが書くべきこと
NetworkManager側のStartHost()を最初に呼んでおきます。(純粋なサーバークライアントモデルの場合はStartServer()です)
その後にNetworkDiscovery内で
Initialize()して
StartAsServer()を呼びます。そうするとNetworkDiscoveryは自動に定期的に(デフォルトで1秒ごとに)ブロードキャストパケットを流します。
定期実行の停止
ゲームを始めます。対戦相手を締め切りました。ゲーム終わるまで追加のプレイヤーは受け付けないようにしたいです。みたいな場合は
StopBroadcast()してあげましょう。そして再びクライアント側を受け付けるときはStartBroadcast()を呼びます。
NetworkDiscoveryのクライアント側でプログラマが書くべきこと
サーバ側と異なり、NetworkManagerのStartClient(NetworkManager.singleton.StartClient(); )は いきなり呼ばないようにします
なぜなら、この時点ではサーバのIPアドレスが分かっていないからです。
NetworkDiscovery内で
Initialize()して
StartAsClient()を呼びます。
そうすると、このクライアント側はNetworkDiscoveryのサーバが流しているブロードキャストパケットを受け取れるようになります。
受け取り先の関数は
public override void OnReceivedBroadcast(string fromAddress, string data)
です。
上に挙げた関数の中で、引数として受け取ったfromAdress(サーバのローカルIPアドレス)を 接続先であるNetworkManagerのnetworkAdress(NetworkManagerのクライアントが接続する先のサーバアドレス)にセットしてから 、NetworkManager.singleton.StartClient(); を呼びます。
よろしいでしょうか。
以下、NetworkDiscoveryの継承先で書くサンプルコードです。自動でサーバに再接続もしてくれます。
(CustomNetworkDiscovery : NetworkDiscovery)
/// <summary>
/// NetworkDiscoveryのクライアント側がサーバの信号を受信したときに呼ばれる
/// この関数は 本クラス内のどこかでStartAsClient()を呼ばないと機能しないし、サーバ側で呼ばれることは無い
/// 初期設定だと、クライアント上で約1秒間隔でこの関数が呼ばれる
/// </summary>
/// <param name="fromAddress">NetworkDiscoveryで見つけたサーバ側のIPアドレス</param>
/// <param name="data"></param>
public override void OnReceivedBroadcast(string fromAddress, string data)
{
//NetworkManagerのnetworkAddress(つまり、サーバのアドレス)に見つけたアドレスを入れる
NetworkManager.singleton.networkAddress = fromAddress;
//既にこのクライアントのNetworkManagerがサーバに接続済みなら何もしない。しかしクライアント側が切断して再接続の時はうまいことreturnせずにスルーして再接続する
if (NetworkManager.singleton.IsClientConnected()==true)
{
return;
}
Debug.LogFormat("OnReceivedBroadcast; fromAddress: {0}, data: {1}", fromAddress, data);
//NetworkManagerのクライアントが繋げる先のサーバアドレスを上で指定しているので、NetworkManagerのクライアントを開始できる
NetworkManager.singleton.StartClient();
}
余談、勝手にサーバになるやつ
最初に起動した人がサーバになる、という仕組みを作りたくなったら、
最初にNetworkDiscoveryのクライアントとして起動して、数秒待ってもサーバが見つからなければサーバとして振る舞う、って書くと良いです。
(この時にNetworkTransportのShutdownとか書いたほうが良いと思うよ!)