LoginSignup
13
14

More than 3 years have passed since last update.

MirrorとLiteNetLib4Mirrorを使って、UnityでのNetwork Discoveryを行うメモ

Last updated at Posted at 2019-07-28

はじめに

LiteNetLib4Mirrorとは、LiteNetLibという.NET用のUDPライブラリを、Unity用ネットワークライブラリMirrorのLow level networking transportとして使えるようにするものです。特に、Mirrorには無いNetwork DiscoveryuPnPをサポートしてくれるのが嬉しいので、その辺の話を中心にメモします。なお、原稿執筆時のLiteNetLib4Mirrorのバージョンは1.2.5です。

LiteNetLib4Mirrorの入手

こちらからUnityPackageをダウンロードして、自分のプロジェクトにインポートしてください。ただし、これにはサンプルシーンが含まれないので、初心者はこちらのレポジトリをクローンして試してみるのが良いと思います。使うUnityのバージョンはUnity 2018.3.6f1以降が推奨です(IL2CPPでのIPv6サポートの問題のため)。私は執筆時点でUnity2018.3.8f1を使ってます。

サンプルシーンから学ぶ

公式ドキュメントが少ないので、サンプルシーンを勉強してみましょう。

レポジトリをクローンしてプロジェクトを開くとAssetフォルダに"Scene"というシーンのファイルがあるので開いてください。Mirrorに付属のPongデモと同じようなシーンが開きます。

image.png

ただし、NetworkManagerゲームオブジェクトにアタッチされてるコンポーネントに、以下のような違いがあります。

LiteNetLib4MirrorTransport

MirrorのPongデモではTelepathy Transportがアタッチされてますが、こちらではLiteNetLib4MirrorTransportがアタッチされています。このコンポーネントはLiteNetLib4Mirrorを使う上で必須であり、必ずNetwork Managerと同じゲームオブジェクトにアタッチされている必要があります。

image.png

コンポーネントのパラメータについては、以下の参考資料が役に立つかもしれません。

127.0.0.1とlocalhostと0.0.0.0の違い
UPnPでNAT越え ~オンラインゲーム開発における課題~

LiteNetLib4MirrorDiscovery

Network Discoveryを行うためのコンポーネントです。On Discovery Responseを設定しておくことで、Hostが見つかった後の処理を行えます。

image.png

NetworkDiscoveryHUD

これがあると、シーンに"Start Discovery"というボタンが表示され、これをClient側で押すとHostを探し始めてくれます。

image.png

Network Manager

このコンポーネント自体はMirrorのPongデモにもありますが、Network Infoの"Transport"がLiteNetLib4MirrorTransportになっているのに注意してください。

image.png

ためしてみる

とりあえず、プロジェクトをビルドして試してください。ビルドしたアプリを二つ起動させて、一方をClient、一方をHostにしてみましょう。Host側で"LAN Host"、Client側で"Start Discovery"を押せば接続されてPongが始まります。
image.png

Network Discoveryの方法

サンプルシーンのNetworkDiscoveryHUD.csが参考になります。この中のOnGUIメソッドの中に、Discoveryを始めるか止めるかの処理があります。コード中の_noDiscoveringは、初期状態ではtrueです。

NetworkDiscoveryHUD.cs
//OnGUI内
if (!NetworkClient.isConnected && !NetworkServer.active){
    if (_noDiscovering){
        if (GUILayout.Button("Start Discovery")){
            StartCoroutine(StartDiscovery());
        }
    }
    else{
        GUILayout.Label("Discovering..");
        GUILayout.Label($"LocalPort: {LiteNetLib4MirrorTransport.Singleton.port}");
        if (GUILayout.Button("Stop Discovery")){
            _noDiscovering = true;
        }
    }
}
else{
    _noDiscovering = true;
}

"Start Discovery"ボタンを押すと、StartDiscoveryメソッドがコルーチンとして実行されます。

StartDiscoveryメソッドでは、LiteNetLib4MirrorDiscoveryコンポーネントのInitializeFinder()で初期化し、Singleton.onDiscoveryResponse.AddListenerでOnClientDiscoveryResponseをイベントハンドラとして登録した後に、LiteNetLib4MirrorDiscovery.SendDiscoveryRequestでリクエストを送信し続けます。

NetworkDiscoveryHUD.cs
private IEnumerator StartDiscovery()
{
    _noDiscovering = false;

    LiteNetLib4MirrorDiscovery.InitializeFinder();
    LiteNetLib4MirrorDiscovery.Singleton.onDiscoveryResponse.AddListener(OnClientDiscoveryResponse);
    while (!_noDiscovering)
    {
        LiteNetLib4MirrorDiscovery.SendDiscoveryRequest("NetworkManagerHUD");
        yield return new WaitForSeconds(discoveryInterval);
    }

    LiteNetLib4MirrorDiscovery.Singleton.onDiscoveryResponse.RemoveListener(OnClientDiscoveryResponse);
    LiteNetLib4MirrorDiscovery.StopDiscovery();
}

サンプルでは、LiteNetLib4MirrorDiscovery.SendDiscoveryRequestの引数として"NetworkManagerHUD"を与えてるのですが、他の文字列を与えても動作に影響しないです。理由は調査中です

(追記: shienaさんのコメントにあるとおり、与えた引数はホスト側のLiteNetLib4MirrorDiscoveryのProcessDiscoveryRequestに渡されるようです。ProcessDiscoveryRequestの中では渡された文字列を使わないので何を与えていても影響ないですが、LiteNetLib4MirrorDiscoveryを継承したクラスを作る場合、この文字列を使って処理を行うこともできます。)

いずれにせよDiscoveryが上手くいくと、登録したOnClientDiscoveryResponseにホストのIP Addressが渡されるので、Mirrorの通常の方法でクライアントを起動できます。

NetworkDiscoveryHUD.cs
private void OnClientDiscoveryResponse(IPEndPoint endpoint, string text)
{
    string ip = endpoint.Address.ToString();
    NetworkManager.singleton.networkAddress = ip;
    NetworkManager.singleton.maxConnections = 2;
    LiteNetLib4MirrorTransport.Singleton.clientAddress = ip;
    LiteNetLib4MirrorTransport.Singleton.port = (ushort)endpoint.Port;
    LiteNetLib4MirrorTransport.Singleton.maxConnections = 2;
    NetworkManager.singleton.StartClient();
    _noDiscovering = true;
}

おわりに

多分、もっと色々なことができるんだと思いますが、サンプルから理解できたのはこれくらいです。公式サンプルが追加されたら、こちらにも情報追加します。

13
14
2

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
13
14