UNET NetworkDiscoveryでIPアドレスの入力を省く

UNETでネットワークゲームを作って、別のマシン同士で通信プレイする際に、面倒なのが、IPアドレスの入力です。

f:id:motoyamablog:20180124152541p:plain

口頭で「いちきゅーにーのー、いちろくはちのー、」とかやるのは、あまりにもスマートじゃないです。

このへんをスマートに解決する機能「NetworkDiscovery」の使い方を紹介します。

概要

NetworkDiscoveryはUNETのコンポーネントで、同一LAN内からサーバー/ホストを自動的に見つけ、IPアドレスの入力を省くための機能です。

同一LAN内に情報を一斉送信する「ブロードキャスト」という技術を使い、他の端末から見つけてもらったり、他の端末を見つけたりします。

ブロードキャストはLAN環境でのみ有効な機能なので、それを利用したNetworkDiscoveryはLAN環境でしか使えません。注意してください。

ぶっちゃけかなり使いづらく、まあ無いよりはマシかなあ、みたいな。(個人の感想です)

解説

NetworkDiscoveryのソースコードこちら。公式リファレンスはこちら

NetworkDiscoveryはServerとClientの2つのモードがあります。Serverは発信者、Clientは受信者です。

Serverモードで起動すると、一定間隔(デフォルトだと1秒間隔)でブロードキャストを行います。

Clientで起動すると、ブロードキャストを受信します。送信者のIPアドレス等がわかります。

主要なメソッド
  • Initialize()
    初期化処理。Server/Clientどちらのモードで使うにしても、とりあえず呼ぶ必要があります。
  • StartAsServer()
    発信者として起動します。
  • StartAsClient()
    受信者として起動します。
  • StopBroadcast()
    発信/受信をやめます。
  • OnReceivedBroadcast()
    ブロードキャストを受信したときに呼ばれるvirtual関数です。空実装になっているので、派生クラスを作ってoverrideする必要があります。
プロパティ

f:id:motoyamablog:20180124161450p:plain

  • Broadcast Port
    ブロードキャストに使うポート番号です。別にそのままで良いと思いますが、問題がある場合は変えてください
  • Broadcast Key / Broadcast Version / Broadcast SubVersion
    これらの値が完全に一致するゲームのインスタンスからのみ、ブロードキャストを受け入れます。同一LAN内に複数種類のゲームが混在している状況や、互換性のない複数バージョンが混在している状況では、これらの値を書き換えてください。
  • Broadcast Interval
    ブロードキャストを送信する間隔(単位はミリ秒)
  • Use NetworkManager
    NetworkManagerと連携して動く(んだと思うんですけど、私の環境だとうまく動かないし、うまくいってもダサいUIで動くだけなので、実用性はあまり無いかと)
  • Broadcast Data
    ブロードキャストに任意の情報を乗せて送信することができます。特に有意義な使い方は思いつきませんが。
  • Show GUI
    オンにすると、OnGUIによるボタンが表示され、NetworkDiscoveryの制御ができます。でもダサいので実用性はほぼ無いと思います。
  • Offset X / Offset Y
    Show GUIがオンのときにGUIを表示する場所

自動でホストに接続するサンプル

ワンクリックでホストを見つけて自動的に接続するサンプルです。

NetworkManagerオブジェクトの作成

空のオブジェクトを新規作成し、「NetworkManager」という名前にします。
NetworkManagerコンポーネントはまだアタッチしません。

NetworkDiscoveryの拡張

標準のNetworkDiscoveryは、ブロードキャストを受信しても何もしてくれないので、ブロードキャストを受信したら送信元のサーバーに自動で接続するように改造します。NetworkManagerオブジェクトに次のスクリプトをアタッチします。

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class MyNetworkDiscovery : NetworkDiscovery
{
    // ブロードキャスト受信時に呼ばれる関数
    public override void OnReceivedBroadcast(string fromAddress, string data)
    {
        NetworkManager manager = NetworkManager.singleton;

        // 既にサーバーまたはクライアントとしてネットワーク接続済みの場合は何もしない
        if (manager.isNetworkActive)
            return;

        // ブロードキャストの送信元IPアドレスを接続先としてセット
        manager.networkAddress = fromAddress;

        // クライアントとして起動する
        manager.StartClient();

        // ブロードキャストの受信をやめる
        StartCoroutine(StopBroadcastCoroutine());
    }

    // ブロードキャストの受信をやめる。
    // OnReceivedBroadcast内でStopBroadcast()を呼ぶと、エラーになってしまうため、
    // 次のフレームで呼ばれるように、コルーチンを使っている。
    IEnumerator StopBroadcastCoroutine()
    {
        yield return new WaitForEndOfFrame();

        // ブロードキャストの送受信をやめる
        StopBroadcast();
    }
}
NetworkManager

NetworkManagerを継承した独自のクラスを作ります。NetworkManagerオブジェクトに次のスクリプトをアタッチします。

using UnityEngine;
using UnityEngine.Networking;

public class MyNetworkManager : NetworkManager
{
    MyNetworkDiscovery m_NetworkDiscovery;

    void Start()
    {
        m_NetworkDiscovery = GetComponent<MyNetworkDiscovery>();
    }

    void OnGUI()
    {
        if (GUI.Button(new Rect(0, 0, 250, 20), "ホストとして起動"))
        {
            // ホストとして起動する
            StartHost();

            // ブロードキャストの送信を開始する
            m_NetworkDiscovery.Initialize();
            m_NetworkDiscovery.StartAsServer();
        }

        if (GUI.Button(new Rect(0, 30, 250, 20), "クライアント(ホストを検索し、接続)"))
        {
            // ブロードキャストの受信を開始する
            m_NetworkDiscovery.Initialize();
            m_NetworkDiscovery.StartAsClient();
        }
    }
    
    // サーバー/ホストとして終了した時に呼ばれる
    public override void OnStopServer()
    {
        // ブロードキャストを終了する
        m_NetworkDiscovery.StopBroadcast();
    }
}

 

NetworkDiscoveryの設定

f:id:motoyamablog:20180124182817p:plain

Show GUI はオフにします。その他の設定はデフォルトで問題無いと思いますが、必要に応じて変更してください。

動作確認

実行ファイルを作成し、PCを2台以上用意して、LANに繋いで動作確認してください。

NetworkDiscoveryは、ブロードキャストを使うので、1台のマシンでは動作確認できません。また、Unityエディターではうまく動きません。

f:id:motoyamablog:20180124184455p:plain

1台をホストとして起動してください。それ以外をクライアントとして起動してください。接続が自動で行われるはずです。(適宜プレイヤーオブジェクト等を追加して確認してください)

今回はあくまでサンプルなので雑なGUIですが、本格的なGUIを作りたい人は、こちらの記事を参考にしてみてください。

 

目次へ