モノビットエンジンでプレイヤー名検索を伴うマッチング機能を作る

MUN(Monobit Unity Networking)を使っていろいろやってみよう！
ということで、プレイヤー検索機能を実装したときのメモです。

環境は以下の通りです
win10 64bit, Unity2018.3.3f1, Monobit Unity Networking2.0 v2.6

##やったこと
クライアントAさん
1. プレイヤー名を入力してサーバ接続
2. ルーム名を入力してルーム作成・入室
 
クライアントBさん
1. プレイヤー名を入力してサーバ接続
2. プレイヤー名を入力してプレイヤー検索
3. 検索結果一覧からプレイヤーを選択してルームに入室

BさんがAさんのいるルームを調べて入室する処理を作ります。
![image01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401086/fdcaca64-7a02-9709-937a-729eee972c9d.png)

```C#:
// プレイヤー名.
private string playerName = "";

/** プレイヤー名入力処理 */

// プレイヤー名を設定
MonobitNetwork.player.name = playerName;

// サーバに接続
MonobitNetwork.ConnectServer("v1.0");
```
プレイヤー名を入力してサーバに接続します。
プレイヤー検索機能はサーバに接続していることが条件なので注意が必要です。
モノビットエンジンが検索処理を行う際は`MonobitNetwork.player.name`を見ます。
プレイヤー名を入れるのを忘れないように注意します。

```C#:
// プレイヤー検索名.
private string searchPlayerName = "";

// プレイヤー検索処理.
void OnGUI_SearchPlayer()
{
    GUILayout.Label("Search Players", new GUIStyle() { fontStyle = FontStyle.Bold });
    GUILayout.BeginHorizontal();
    GUILayout.Label("Player Name: ");
    searchPlayerName = GUILayout.TextField(searchPlayerName, GUILayout.Width(150));
    if(GUILayout.Button("Seatch", GUILayout.Width(150)))
    {
        // プレイヤー名で検索する
        if(!string.IsNullOrEmpty(searchPlayerName))
        {
            // コルーチンで実行
            StartCoroutine("SearchPlayer");
        }
    }
    GUILayout.EndHorizontal();
}
```

![image02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401086/ada705b7-5301-5c3a-64d5-8d2dba6dd388.png)

プレイヤー名を入力して”Search”ボタンを押すと検索処理へと移ります。
プレイヤー検索は場合によっては時間がかかるので`StartCoroutine()メソッド`を使いコルーチンを実行します。
コルーチンについてはこちら([参考リンク]
(http://developer.wonderpla.net/entry/blog/engineer/Unity_Co-routine/))

```C#:
// プレイヤー検索(コルーチン).
private IEnumerator SearchPlayer()
{
    isSearchPlayer = false;

    // プレイヤー検索リスト作成
    string[] searchNameList = searchPlayerName.Split(' ');

    // 検索
    MonobitNetwork.SearchPlayers(searchNameList);

    // 見つかるまでループ
    while(!isSearchPlayer)
    {
        yield return null;
    }
}
```
検索フィールドにスペース区切りで名前を入れると、複数名の検索が可能です。
`string[] searchNameList = searchPlayerName.Split(' ');`でプレイヤー名配列を作成します。
その配列を`MonobitNetwork.SearchPlayers();`に渡して検索をします。
また、コルーチンに処理を渡したあと内部ではプレイヤーが見つかるまでループし続けます。

```C#:
// プレイヤー検索結果が返ってきたときのコールバック.
public void OnUpdatedSearchPlayers()
{
    isSearchPlayer = true;
}
```
検索を終えると`OnUpdatedSearchPlayersコールバック`が呼ばれるのでフラグをtrueにし、コルーチンのループを抜けます。

```C#:
// 検索結果が得られたかどうか.
private bool isSearchPlayer = false;

// プレイヤー検索結果の表示.
void OnGUI_SearchPlayerResult()
{
    // 検索中なら以下無視
    if(!isSearchPlayer)
    {
        return;
    }

    GUILayout.Label("Search Result", new GUIStyle() { fontStyle = FontStyle.Bold });
    foreach(SearchPlayerData player in MonobitNetwork.SearchPlayerList)
    {
        if(!player.connect)
        {
            GUILayout.Label(player.playerName + " is offline.");
        }
        else if(!player.inRoom)
        {
            GUILayout.Label(player.playerName + " is not in room.");
        }
        else
        {
            GUILayout.Label(player.playerName + " is in " + player.roomName);
            
            // 参加する
            if (GUILayout.Button("Join", GUILayout.Width(150)))
            {
                MonobitNetwork.JoinRoom(player.roomName);
            }
        }
    }
}
```
最後に結果を取得して表示します。
`MonobitNetwork.SearchPlayers()`を実行後、検索を終え`OnUpdatedSearchPlayers()コールバック`が呼ばれると、結果は`SearchPlayerData型`の`MonobitNetwork.SearchPlayerListプロパティ`に格納されています。
foreachでリストからデータを取りだし、ひとつひとつチェックしていきます。([参考リンク](http://www.monobitengine.com/doc/mun/contents/FeatureClient/SearchPlayers.htm#MonobitEngine.MonobitNetwork.SearchPlayerList%20%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3))
![image4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401086/41e96a81-3f89-30ac-3764-5cb2c66b0931.png)

##参考リンク
- [Monobit Unity Networking2.0公式リンク](http://www.monobitengine.com/doc/mun/)
- [コルーチンについて](http://developer.wonderpla.net/entry/blog/engineer/Unity_Co-routine/)