LoginSignup
7
7

More than 5 years have passed since last update.

UNET NetworkManager のコールバックについての注意点

Last updated at Posted at 2016-06-16

前置き

Unity5.3.4です

NetworkManagerについての初手からの詳細説明は凹みさんのこちらをまずはお進めします。
http://tips.hecomi.com/entry/2015/08/14/220030

2016.06.18 追記
NetworkManagerクラスなどはオープンソース化されていたんですね・・・uGUIと同じく、このソースを見ながら独自に修正しろよ、という趣。
https://bitbucket.org/Unity-Technologies/networking

本題

NetworkManagerクラスはそのまま使うのではなく、継承して使うのが良くあるやり方になるのかなと思います。
何かのきっかけで発火する関数がC#のイベント、デリゲートではなく、overrideして使うようになっているからです。

以下悪い例です、なぜ悪いのかは後述します。

badsample.cs
public class MyNetworkManager : NetworkManager 
{

    //サーバーに接続したときクライアント上で呼び出されます。
    public override void OnClientConnect(NetworkConnection conn)
    {
        // Do Something...
    }

    //サーバーが切断されたときにクライアント上で呼び出されます。
    public override void OnClientDisconnect(NetworkConnection conn)
    {
        // Do Something...
    }
}

NetworkManagerクラスでoverrideできる関数としては以下です。たくさんありますが検索で引っかかるように全部羅列しておきます。

public virtual void OnClientConnect(NetworkConnection conn);
public virtual void OnClientDisconnect(NetworkConnection conn);
public virtual void OnClientError(NetworkConnection conn, int errorCode);
public virtual void OnClientNotReady(NetworkConnection conn);
public virtual void OnClientSceneChanged(NetworkConnection conn);
public virtual void OnMatchCreate(CreateMatchResponse matchInfo);
public virtual void OnMatchList(ListMatchResponse matchList);
public virtual void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader);
public virtual void OnServerAddPlayer(NetworkConnection conn, short playerControllerId);
public virtual void OnServerConnect(NetworkConnection conn);
public virtual void OnServerDisconnect(NetworkConnection conn);
public virtual void OnServerError(NetworkConnection conn, int errorCode);
public virtual void OnServerReady(NetworkConnection conn);
public virtual void OnServerRemovePlayer(NetworkConnection conn, PlayerController player);
public virtual void OnServerSceneChanged(string sceneName);
public virtual void OnStartClient(NetworkClient client);
public virtual void OnStartHost();
public virtual void OnStartServer();
public virtual void OnStopClient();
public virtual void OnStopHost();
public virtual void OnStopServer();
public virtual void ServerChangeScene(string newSceneName);
public virtual NetworkClient StartHost(ConnectionConfig config, int maxConnections);
public virtual NetworkClient StartHost(MatchInfo info);
public virtual NetworkClient StartHost();

注意点です。(ここが要旨すべてです)
上記関数を override して使う場合は、必ず基底クラスの関数を呼び出しましょう!

goodsample.cs
public class MyNetworkManager : NetworkManager 
{

    //サーバーに接続したときクライアント上で呼び出されます。
    public override void OnClientConnect(NetworkConnection conn)
    {
        base.OnClientConnect(conn);<<<<<重要
        // Do Something...
    }

    //サーバーが切断されたときにクライアント上で呼び出されます。
    public override void OnClientDisconnect(NetworkConnection conn)
    {
        base.OnClientDisconnect(conn);<<<<<重要
        // Do Something...
    }
}

基底クラスの関数の実行を忘れると
「あるコールバックをオーバーライドすると、違うコールバックが発動しなくなる。つまり、仕様(リファレンス)通りに呼び出されなくなる」
という現象が起きます。
コールバックが呼び出されないばかりか、ネットワーク関連に何か不都合が起きるようで、UNETの機能がもろもろおかしくなっていきます。簡潔にいって、UNETぶっ壊れます。
これはキビシイです。
どうやら、NetworkManagerでvirtual指定されている関数群は空実装でないものがあるようです。
2016.06.18 追記
どうやら、ではなく、ソースを確認すると間違いなくそうなっていました。

正直この実装はミスってると思いますが、そうなってるのでしょうがない・・・

現在Unity5.3.4で確認しているものでは
OnClientConnect をoverrideして、base.OnClientConnect を呼び出さないでいると、
OnServerReady が呼ばれることはありません。

ご注意くださいませ。

おまけの質問コーナー

NetworkServer.active==true

になるきっかけはどうやって取れば良いのでしょうか?
どなたか良い方法をご存知の方がいらっしゃいましたら教えていただきたく思います。

public virtual void OnServerReady(NetworkConnection conn);
は、「Called on the server when a client is ready.」
というコールバックであってサーバー起動直後に実行されるコールバックではないようです。
クライアントが複数の場合それらが接続してくるたびにコールされます。

また、

public virtual void OnStartServer();
が呼び出されるタイミングではNetworkServer.active==falseになっており、プレハブをSpawnすることができません。

Called on the server when a server is ready.
のコールバックがみあたらず、しょうがなくOnServerReadyを初期化フラグとともに使っていますが・・・

public override void OnServerReady(NetworkConnection conn)
{
    if(_InitFlg==false)
    {
        _InitFlg = true;
        NetworkServer.Spawn( prefab );      //サーバー&クライアントで共有するオブジェクトをひとつだけ作りたい
    }
}

ダサい、ダサすぎる。
もっといけてるやり方があるように思うのです。

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