読者です 読者をやめる 読者になる 読者になる

tanaka's Programming Memo

プログラミングについてのメモ。

UnetのNetworkDiscoveryでLANのサーバーに自動接続

Unity5.2にNetworkDiscoveryというコンポーネントが追加されました。これまでは、マッチングサーバーを使わずにLANのサーバーやホストに接続する場合は、NetworkManagerにIPを指定していましたが、NetworkDiscoveryを利用すると自動的にクライアントがサーバーを見つけて接続できるようになります。

NetworkDiscoveryを使って、クライアントとサーバーが接続する簡単な例を紹介します。開発したのはVer5.2.1です。

実行ファイル

以下からWindows用の実行ファイルがダウンロードできます。

基礎知識

NetworkDiscoveryのリファレンスマニュアル

Unity - Scripting API: NetworkDiscovery

NetworkDiscoveryのリファレンスの冒頭のざっくり和訳

NetworkDiscoveryは、ローカルネットワーク上でお互いのゲームを見つけるためのコンポーネントです。ブロードキャストを使ってお互いを見つけることができます。サーバーを見つけたクライアントに自動的にNetworkManagerにクライアントとして接続させることもできます。

このコンポーネントはStartAsServerを呼び出してサーバーモードで起動すると動作を開始します。サーバーが起動するとローカルネットワーク上の他のコンピューターに自分の情報をブロードキャストします。StartAsClientでクライアントモードで実行したゲームは、サーバーからのブロードキャストを受け取り、サーバーがどこにあるかを知ることができます。

(補足)
NetworkDiscoveryにはシンプルなGUIが用意されています。製品版に利用できる見た目や操作性ではありませんが、テストであればこれで簡単に機能を試すことができます。

NetworkDiscoverはLAN上にいる他のゲームを見つけるためのものです。マルチプレイヤーゲームとして動作させるためにはNetworkManagerが必要です。

サンプルの概要

  • Sphereで作成したカーソルキーで操作できる簡易プレイヤーを、マルチプレイヤーで動かせるサンプルを開発する
  • NetworkDiscoveryの手続きは組み込みGUIを利用
  • NetworkDiscoveryがサーバーで起動されたら、NetworkManagerをHostで起動する
  • NetworkManagerが接続されたら、NetworkDiscoveryのGUIを消す
  • NetworkDiscoveryのクライアントは自動化されているので特にやることはない

サンプルの実装

テスト用のプレイヤーを作成する

  • [Hierarchy]ビューの[Create]から[3D Object]>[Sphere]を選択
  • 名前を[Player]に変更
  • [Inspector]ビューから[Add Component]>[Physics]>[Rigidbody]を選択
  • [Inspector]ビューの[Rigidbody]コンポーネント欄の[Use Gravity]を外す
  • [Inspector]ビューから[Add Component]>[New Script]を選択
  • スクリプト名を「CPlayer]として、[Create and Add]で追加
  • [CPlayer]をダブルクリックしてエディターで開く
  • 以下のスクリプトを入力
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class CPlayer : NetworkBehaviour {
    /** 移動速度*/
    public float speed = 10f;
    /** リジッドボディのインスタンス*/
    private Rigidbody rig;

    // Use this for initialization
    void Start () {
        rig = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void FixedUpdate () {
        // 制御権がない場合は実行しない
        if (!hasAuthority) return;

        // 操作
        Vector3 move = Vector3.zero;
        move.x = Input.GetAxisRaw("Horizontal");
        move.y = Input.GetAxisRaw("Vertical");
        move = move.normalized * speed;
        rig.velocity = move;
    }
}
  • 実行して動作を確認する
プレイヤーをネットワーク対応させる
  • [Hierarchy]ビューの[Player]を選択
  • [Inspector]ビューから[Add Component]>[Network]>[NetworkTransform]を追加
  • [Inspector]ビューの[NetworkIdentity]コンポーネント欄の[Local Player Authority]をチェック
  • [Hierarchy]ビューの[Player]をドラッグして、[Project]ビューにドロップしてプレハブ化する

NetworkDiscoverを追加したNetworkManagerのゲームオブジェクトを作成

  • [Ctrl]+[Shift]+[N]で空のゲームオブジェクトを作成
  • 名前を[NetworkManager]に変更
  • [Inspector]ビューから[Add Component]>[Network]>[NetworkManager]を追加
  • [Inspector]ビューから[Add Component]>[Network]>[NetworkDiscovery]を追加
  • [Inspector]ビューの[NetworkManager]コンポーネント欄の[Spawn Info]の左の▼を押して開く
  • [Project]ビューの[Player]をドラッグして、[Inspector]ビューの[Player Prefab]欄にドロップ

動作確認

  • [Ctrl]キー+[S]でシーンを保存。名前は[discover]など
  • [File]メニューから[Build Settings...]を選択
  • ウィンドウ中央右の[Add Current]ボタンを押してシーンを追加
  • ウィンドウ下の[Player Settings...]ボタンを押す
  • [Inspector]ビューから[Resolution and Presentation]を開く
  • [Default Is Full Screen]のチェックを外す
  • [Default Screen Width]を「640」、[Default Screen Height]を「480」などにする
  • [Run In Background]をチェックする
  • [Build & Run]ボタンを押してビルド
  • ビルドが完了してプログラムが起動したら[Play]で開始
  • [Initialize Broadcast]ボタンを押す
  • [Start Broadcasting]ボタンを押す。これで、サーバーとして自分の場所をローカルネット上にブロードキャストし始める
  • [Unity]を実行する
  • [Initialize Broadcast]ボタンを押す
  • [Listen for Broadcast]ボタンを押す
  • サーバーからのブロードキャストメッセージを受け取ると、画面に[Game at ::・・・]というようにサーバーのアドレスが表示される

以上でクライアントからサーバーが見つけられることが確認できました。あとはNetworkManagerを適切に設定すればサーバーを見つけてマルチプレイヤーで実行できます。

NetworkManagerの制御用のスクリプトを作成する

  • [Inspector]ビューから[Add Component]>[New Script]を選択
  • [CNetDiscovery]という名前にして、[Create and Add]
  • [CNetDiscovery]をダブルクリックしてエディターで開く
  • 以下のスクリプトを入力する
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class CNetDicovery : MonoBehaviour {
    /** NetworkDiscovery*/
    private NetworkDiscovery netdisc;
    /** NetworkManager*/
    private NetworkManager netman;

    // Use this for initialization
    void Start () {
        netman = GetComponent<NetworkManager>();
        netdisc = GetComponent<NetworkDiscovery>();
    }
	
    // Update is called once per frame
    void Update () {
        // NetworkManagerが開始していない時に処理
        if (netdisc.showGUI)
        {
            // NetworkDiscoveryがサーバーとして動作していたら、NetworkManagerをHostで開始する
            if (netdisc.isServer)
            {
                // ホストとして開始
                netman.StartHost();
            }

            // NetworkManagerが開始していたらGUIを消す
            if (netman.isNetworkActive)
            {
                netdisc.showGUI = false;
            }
        }	
    }
}
  • 上書き保存をしたらUnityに切り替える
  • [Build & Run]でリビルド

完成

以上で完成です。以下の手順で実行します。

  • ビルドして実行したアプリを[Play]で開始
  • [Initialize Broadcast]を押す
  • [Start Broadcasting]を押すとホストとして開始
  • Unityを実行
  • [Initialize Broadcast]を押す
  • [Listen for Broadcast]を押す
  • サーバーが見つかると[Game ・・・]というボタンが表示されるので、それを押す

以上でプレイヤーが2つ画面に登場します。プレイヤーはカーソルキーで操作することができます。

未確認&動作制限

  • ファイアーウォールでUDPが許可できない環境だと動作しない
  • 同一PC上で2つ目のクライアントを起動しようとするとエラーが発生する
  • 別PCでの接続は未確認(動作が確認でき次第、追記します)