17
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UnityのUNETにおけるローカルLAN対戦の為のNetworkDiscovery

Last updated at Posted at 2018-02-15

概要

細かい挙動までは書きませんが、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とか書いたほうが良いと思うよ!)

17
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?