UNET NetworkDiscoveryでIPアドレスの入力を省く
UNETでネットワークゲームを作って、別のマシン同士で通信プレイする際に、面倒なのが、IPアドレスの入力です。
口頭で「いちきゅーにーのー、いちろくはちのー、」とかやるのは、あまりにもスマートじゃないです。
このへんをスマートに解決する機能「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する必要があります。
プロパティ
- 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の設定
Show GUI はオフにします。その他の設定はデフォルトで問題無いと思いますが、必要に応じて変更してください。
動作確認
実行ファイルを作成し、PCを2台以上用意して、LANに繋いで動作確認してください。
NetworkDiscoveryは、ブロードキャストを使うので、1台のマシンでは動作確認できません。また、Unityエディターではうまく動きません。
1台をホストとして起動してください。それ以外をクライアントとして起動してください。接続が自動で行われるはずです。(適宜プレイヤーオブジェクト等を追加して確認してください)
今回はあくまでサンプルなので雑なGUIですが、本格的なGUIを作りたい人は、こちらの記事を参考にしてみてください。