マッチメイキング

目次

  概要
  ルーム選択型のプレイヤーマッチング
  ランダムマッチング
  ルームフィルタ
  クエリー検索マッチング
  ランク値検索マッチング
  プレイヤー名検索マッチング


概要

MUNでサポートする「プレイヤーマッチング」の手法について

  この項目以降は技術的な話を取り上げます。
  現時点で MUN がサポートしている「プレイヤーマッチング」の手法について紹介します。


ルーム選択型のプレイヤーマッチング

マッチングを自動化せず、プレイヤー自身が手動で行なう方法

  以下のようなスクリプトを組むことで、ルーム選択型のプレイヤーマッチングが可能です。
  (簡易仕様のため、接続コールバック等による例外処理を省いております)
using UnityEngine;

namespace MonobitEngine.Sample
{
    // ルーム選択型プレイヤーマッチング
    public class SelectRoomMatchMaking : MonobitEngine.MonoBehaviour
    {
        // ルーム名
        private string roomName = "";
        
        // 開始関数
        public void Awake()
        {
            // デフォルトロビーへの強制入室をONにする。
            MonobitEngine.MonobitNetwork.autoJoinLobby = true;
            
            // サーバに接続する
            MonobitEngine.MonobitNetwork.ConnectServer("SelectRoomMatchMaking_v1.0");
        }
        
        // GUIまわりの記述
        public void OnGUI()
        {
            // GUI用の解像度を調整する
            Vector2 guiScreenSize = new Vector2(800, 480); // 標準解像度
            GUIUtility.ScaleAroundPivot(new Vector2(Screen.width / guiScreenSize.x, Screen.height / guiScreenSize.y), Vector2.zero);
            
            // 未接続なら何もしない
            if (!MonobitEngine.MonobitNetwork.isConnect)
            {
                return;
            }
            
            // ルーム入室中の場合
            if (MonobitEngine.MonobitNetwork.inRoom)
            {
                // ルーム名表示
                GUILayout.Label("InRoom : " + MonobitEngine.MonobitNetwork.room.name);
                
                // 退室ボタン表示
                if(GUILayout.Button("Leave Room"))
                {
                    MonobitEngine.MonobitNetwork.LeaveRoom();
                }
            }
            // ルーム未入室・退室後の場合
            else
            {
                // ルーム作成ボタンの作成
                GUILayout.BeginHorizontal();
                GUILayout.Label("RoomName : ");
                roomName = GUILayout.TextField(roomName, GUILayout.Width(200));
                if(GUILayout.Button("Create Room"))
                {
                    MonobitEngine.MonobitNetwork.CreateRoom(roomName);
                }
                GUILayout.EndHorizontal();
                
                // ルーム一覧からボタン選択
                foreach (MonobitEngine.RoomData room in MonobitEngine.MonobitNetwork.GetRoomData())
                {
                    if (GUILayout.Button("Join Room : " + room.name + "(" + room.playerCount + "/" + room.maxPlayers + ")" ))
                    {
                        MonobitEngine.MonobitNetwork.JoinRoom(room.name);
                    }
                }
            }
        }
    }
}


ランダムマッチング

現在存在するルームの中からランダムに選択してマッチングする方法

  以下のようなスクリプトを組むことで、ランダムマッチングが可能です。
  (簡易仕様のため、接続コールバック等による例外処理を省いております)
using UnityEngine;

namespace MonobitEngine.Sample
{
    // ランダムマッチング
    public class RandomMatchMaking : MonobitEngine.MonoBehaviour
    {
        // ルーム名
        private string roomName = "";
        
        // 開始関数
        public void Awake()
        {
            // デフォルトロビーへの強制入室をONにする。
            MonobitEngine.MonobitNetwork.autoJoinLobby = true;
            
            // サーバに接続する
            MonobitEngine.MonobitNetwork.ConnectServer("RandomMatching_v1.0");
        }
        
        // GUIまわりの記述
        public void OnGUI()
        {
            // GUI用の解像度を調整する
            Vector2 guiScreenSize = new Vector2(800, 480); // 標準解像度
            GUIUtility.ScaleAroundPivot(new Vector2(Screen.width / guiScreenSize.x, Screen.height / guiScreenSize.y), Vector2.zero);
            
            // 未接続なら何もしない
            if (!MonobitEngine.MonobitNetwork.isConnect)
            {
                return;
            }
            
            // ルーム入室中の場合
            if (MonobitEngine.MonobitNetwork.inRoom)
            {
                // ルーム名表示
                GUILayout.Label("InRoom : " + MonobitEngine.MonobitNetwork.room.name);
                
                // 退室ボタン表示
                if(GUILayout.Button("Leave Room"))
                {
                    MonobitEngine.MonobitNetwork.LeaveRoom();
                }
            }
            // ルーム未入室・退室後の場合
            else
            {
                // ルーム作成ボタンの作成
                GUILayout.BeginHorizontal();
                GUILayout.Label("RoomName : ");
                roomName = GUILayout.TextField(roomName, GUILayout.Width(200));
                if(GUILayout.Button("Create Room"))
                {
                    MonobitEngine.MonobitNetwork.CreateRoom(roomName);
                }
                GUILayout.EndHorizontal();
                
                // ボタン入力でランダム入室
                if (GUILayout.Button("Join Random Room"))
                {
                    MonobitEngine.MonobitNetwork.JoinRandomRoom();
                }
            }
        }
    }
}


ルームフィルタ

現在存在するルームの中から、キーワードが一致するルームを検出してマッチングする方法

  以下のようなスクリプトを組むことで、パスワードロックの掛かったルーム入室制御が可能です。
  (簡易仕様のため、接続コールバック等による例外処理を省いております)
using UnityEngine;
using System.Collections;

namespace MonobitEngine.Sample
{
    public class RoomFilter : MonobitEngine.MonoBehaviour
    {
        // ルーム名
        string roomName = "";
        
        // カスタムパラメータリスト
        Hashtable customRoomParam = new Hashtable();
        
        // パスワード入力群
        Hashtable joinRoomPassword = new Hashtable();
        
        /**
         * 開始関数.
         */
        public void Awake()
        {
            // デフォルトロビーへの強制入室をONにする
            MonobitNetwork.autoJoinLobby = true;
            
            // MUNサーバに接続する
            MonobitNetwork.ConnectServer("RoomFilter_v1.0");
        }
        
        /**
         * GUIまわりの記述.
         */
        public void OnGUI()
        {
            // GUI用の解像度を調整する
            Vector2 guiScreenSize = new Vector2(800, 480); // 標準解像度
            GUIUtility.ScaleAroundPivot(new Vector2(Screen.width / guiScreenSize.x, Screen.height / guiScreenSize.y), Vector2.zero);
            
            // サーバとの接続が終わってなければ何もしない
            if( !MonobitNetwork.isConnect )
            {
                return;
            }
            // まだルーム未入室の場合
            else if (!MonobitNetwork.inRoom)
            {
                OnGUI_OutOfRoom();
            }
            // ルーム入室中の場合
            else
            {
                OnGUI_InRoom();
            }
        }
        
        /**
         * 接続中&ルーム未入室状態でのOnGUI制御.
         */
        private void OnGUI_OutOfRoom()
        {
            // ルーム作成
            OnGUI_CreateRoom();
            
            // ルーム入室
            OnGUI_JoinRoom();
        }
        
        /**
         * ルーム作成.
         */
        private void OnGUI_CreateRoom()
        {
            // 表題
            GUILayout.Label("Create Room", new GUIStyle() { normal = new GUIStyleState() { textColor = Color.white }, fontStyle = FontStyle.Bold });
            GUILayout.BeginHorizontal();
            GUILayout.Space(25);
            
            // ルーム名入力
            GUILayout.Label("RoomName : ");
            this.roomName = GUILayout.TextField(this.roomName, GUILayout.Width(200));
            
            // ルームのカスタムパラメータ(パスワード)の値入力
            GUILayout.Label("Password : ");
            this.customRoomParam["Password"] = GUILayout.TextField((this.customRoomParam.ContainsKey("Password")) ? this.customRoomParam["Password"].ToString(): "", GUILayout.Width(200));
            
            // 任意の名称を持つルームを作成する
            if (GUILayout.Button("Create Room", GUILayout.Width(150)))
            {
                // カスタムルームパラメータの設定
                RoomSettings roomSettings = new RoomSettings()
                {
                    isVisible = true,
                    isOpen = true,
                    customRoomParameters = this.customRoomParam,
                    customRoomParametersForLobby = new string[]{ "Password" }
                };
                
                MonobitNetwork.CreateRoom(this.roomName, roomSettings, null);
            }
            
            GUILayout.EndHorizontal();
        }
        
        /**
         * ルーム入室.
         */
        private void OnGUI_JoinRoom()
        {
            // 表題
            GUILayout.Label("Join Room", new GUIStyle() { normal = new GUIStyleState() { textColor = Color.white }, fontStyle = FontStyle.Bold });
            GUILayout.BeginVertical();
            
            // 既存のルーム一覧情報からルーム情報を抽出
            foreach( RoomData roomData in MonobitNetwork.GetRoomData())
            {
                GUILayout.BeginHorizontal();
                GUILayout.Space(25);
                
                // ルーム名の表示
                GUILayout.Label("RoomName : " + roomData.name);
                
                // パスワードの値入力
                GUILayout.Label("Password : ");
                this.joinRoomPassword[roomData.name] = GUILayout.TextField((this.joinRoomPassword.ContainsKey(roomData.name))?this.joinRoomPassword[roomData.name].ToString(): "", GUILayout.Width(200));
                
                // 該当するルームに入室する
                if (GUILayout.Button("Join Room", GUILayout.Width(150)))
                {
                    // カスタムルームパラメータへの登録
                    this.customRoomParam["Password"] = this.joinRoomPassword[roomData.name];
                    
                    MonobitNetwork.JoinRandomRoom(this.customRoomParam, 0);
                    
                    this.customRoomParam["Password"] = "";
                }
                
                GUILayout.EndHorizontal();
            }
            
            GUILayout.EndVertical();
        }
        
        /**
         * ルーム内でのGUI操作.
         */
        private void OnGUI_InRoom()
        {
            // ルーム名の表示
            GUILayout.Label("InRoom : " + MonobitNetwork.room.name);
            
            // ルーム退室
            if( GUILayout.Button("Leave Room", GUILayout.Width(100)))
            {
                MonobitNetwork.LeaveRoom();
            }
        }
    }
}


クエリー検索マッチング

現在存在するルームの中から、該当するルームカスタムパラメータの値範囲が一致するルームを検出してマッチングする方法

  以下のようなスクリプトを組むことで、SQLクエリー構文のようなルーム範囲検索マッチングが可能です。
  (簡易仕様のため、必要最低限のみの接続コールバックのみを用意し、例外処理を省いております)
using UnityEngine;
using System.Collections;

namespace MonobitEngine.Sample
{
    public class QueryMatching : MonobitEngine.MonoBehaviour
    {
        // カスタムパラメータリスト
        Hashtable customRoomParam = new Hashtable();
        
        // カスタムパラメータキー(GUI入力用)
        string customRoomKey = "";
        
        // クエリー照合パラメータ
        string keyValueFilter = "";
        
        /**
         * 開始関数.
         */
        public void Awake()
        {
            // デフォルトロビーへの強制入室をOFFにする
            MonobitNetwork.autoJoinLobby = false;
            
            // MUNサーバに接続する
            MonobitNetwork.ConnectServer("QueryMatching_v1.0");
        }
        
        /**
         * GUIまわりの記述.
         */
        public void OnGUI()
        {
            // GUI用の解像度を調整する
            Vector2 guiScreenSize = new Vector2(800, 480); // 標準解像度
            GUIUtility.ScaleAroundPivot(new Vector2(Screen.width / guiScreenSize.x, Screen.height / guiScreenSize.y), Vector2.zero);
            
            // サーバと未接続の場合何もしない
            if (!MonobitNetwork.isConnect)
            {
                return;
            }
            // まだルーム未入室の場合
            else if (!MonobitNetwork.inRoom)
            {
                OnGUI_OutOfRoom();
            }
            // ルーム入室中の場合
            else
            {
                OnGUI_InRoom();
            }
        }
        
        /**
         * 接続中&ルーム未入室状態でのOnGUI制御.
         */
        private void OnGUI_OutOfRoom()
        {
            // ロビー未入室の場合、何もしない
            if (!MonobitNetwork.inLobby)
            {
                return;
            }
            
            // ルームの作成設定
            OnGUI_CreateRoom();
            
            // ルームの入室設定
            OnGUI_JoinRoom();
        }
        
        /**
         * ルーム作成設定.
         */
        private void OnGUI_CreateRoom()
        {
            // 表題
            GUILayout.Label("Create Room", new GUIStyle() { normal = new GUIStyleState() { textColor = Color.white }, fontStyle = FontStyle.Bold });
            GUILayout.BeginHorizontal();
            GUILayout.Space(25);
            GUILayout.BeginVertical();
            GUILayout.Label("Custom Parameters");
            
            // ルームのカスタムパラメータの値入力
            if (this.customRoomParam.Count > 0)
            {
                Hashtable tmp = new Hashtable(this.customRoomParam);
                foreach (string key in this.customRoomParam.Keys)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Key : " + key + ", Value : ", GUILayout.Width(125));
                    tmp[key] = GUILayout.TextField(this.customRoomParam[key].ToString(), GUILayout.Width(200));
                    if (GUILayout.Button("Remove", GUILayout.Width(75)))
                    {
                        tmp.Remove(key);
                    }
                    GUILayout.EndHorizontal();
                }
                this.customRoomParam = tmp;
            }
            
            // ルームのカスタムパラメータのキー追加
            GUILayout.BeginHorizontal();
            GUILayout.Label("New Key : ", GUILayout.Width(100));
            customRoomKey = GUILayout.TextField(customRoomKey, GUILayout.Width(200));
            if (GUILayout.Button("Add", GUILayout.Width(75)))
            {
                if (!string.IsNullOrEmpty(customRoomKey))
                {
                    this.customRoomParam[customRoomKey] = "" as object;
                    customRoomKey = "";
                }
            }
            GUILayout.EndHorizontal();
            
            // 任意の名称を持つルームを作成する
            if (GUILayout.Button("Create Room", GUILayout.Width(150)))
            {
                // カスタムルームパラメータから、ロビー送信パラメータを抽出(とりあえず全部送信するようにする)
                string[] customRoomParametersForLobby = new string[this.customRoomParam.Keys.Count];
                int keyIndex = 0;
                foreach (string key in this.customRoomParam.Keys)
                {
                    customRoomParametersForLobby[keyIndex] = key;
                    keyIndex++;
                }
                
                RoomSettings roomSettings = new RoomSettings()
                {
                    isVisible = true,
                    isOpen = true,
                    maxPlayers = 0,
                    customRoomParameters = this.customRoomParam,
                    customRoomParametersForLobby = customRoomParametersForLobby
                };
                
                MonobitNetwork.CreateRoom(null, roomSettings, null);
            }
            
            GUILayout.EndVertical();
            GUILayout.EndHorizontal();
        }
        
        /**
         * ルーム入室設定.
         */
        private void OnGUI_JoinRoom()
        {
            // 表題
            GUILayout.Label("Join Room", new GUIStyle() { normal = new GUIStyleState() { textColor = Color.white }, fontStyle = FontStyle.Bold });
            GUILayout.BeginHorizontal();
            GUILayout.Space(25);
            GUILayout.BeginVertical();
            
            // クエリー文の入力
            GUILayout.BeginHorizontal();
            GUILayout.Label("Key Values : ");
            this.keyValueFilter = GUILayout.TextField(this.keyValueFilter, GUILayout.Width(400));
            GUILayout.EndHorizontal();
            
            // カスタムルームパラメータと一致するランダム入室
            if (GUILayout.Button("Join Room", GUILayout.Width(150)))
            {
                MonobitNetwork.JoinRandomRoom(null, 0, Definitions.MatchmakingMode.SerialMatching, new LobbyInfo() { Kind = LobbyKind.Query, Name = "QueryLobby" }, this.keyValueFilter);
            }
            
            GUILayout.EndVertical();
            GUILayout.EndHorizontal();
        }
        
        /**
         * ルーム内でのGUI操作.
         */
        private void OnGUI_InRoom()
        {
            // ルームの入室制限可否設定の表示
            GUILayout.Label("InRoom : " + MonobitNetwork.room.name);
            
            // 部屋からの離脱
            if (GUILayout.Button("Leave Room", GUILayout.Width(100)))
            {
                MonobitNetwork.LeaveRoom();
            }
        }
        
        /**
         * サーバ接続成功時の処理.
         */
        public void OnConnectedToServer()
        {
            Debug.Log("OnConnectedToServer");
            
            // クエリーロビーに入室
            MonobitNetwork.JoinLobby(new LobbyInfo() { Kind = LobbyKind.Query, Name = "QueryLobby" });
        }
    }
}


ランク値検索マッチング

現在存在するルームの中から、自分のランク値に近いルーム作成者のいるルームを検出してマッチングする方法

  以下のようなスクリプトを組むことで、ランク値を基準にしたルーム検索マッチングが可能です。
  (簡易仕様のため、必要最低限のみの接続コールバックのみを用意し、例外処理を省いております)
using System;
using UnityEngine;
using System.Collections;

namespace MonobitEngine.Sample
{
    public class RankMatching : MonobitEngine.MonoBehaviour
    {
        // カスタムパラメータリスト
        Hashtable customRoomParam = new Hashtable();
        
        // クエリー検索で範囲検索をする際のランク値範囲の閾値
        private int baseValue = 0;            // 基準値
        private int baseValueMax = 0;         // 最小値
        private int baseValueMin = 0;         // 最大値
        private int baseValueIncrease = 5;    // 閾値の±増分
        private int baseValueHigh = 100;      // 範囲検索の最大上限
        private int baseValueLow = 0;         // 範囲検索の最小下限
        
        /**
         * 開始関数.
         */
        public void Awake()
        {
            // デフォルトロビーへの強制入室をOFFにする
            MonobitNetwork.autoJoinLobby = false;
            
            // MUNサーバに接続する
            MonobitNetwork.ConnectServer("RankMatching_v1.0");
        }
        
        /**
         * GUIまわりの記述.
         */
        public void OnGUI()
        {
            // GUI用の解像度を調整する
            Vector2 guiScreenSize = new Vector2(800, 480); // 標準解像度
            GUIUtility.ScaleAroundPivot(new Vector2(Screen.width / guiScreenSize.x, Screen.height / guiScreenSize.y), Vector2.zero);
            
            // サーバと未接続の場合何もしない
            if (!MonobitNetwork.isConnect)
            {
                return;
            }
            // まだルーム未入室の場合
            else if (!MonobitNetwork.inRoom)
            {
                OnGUI_OutOfRoom();
            }
            // ルーム入室中の場合
            else
            {
                OnGUI_InRoom();
            }
        }
        
        /**
         * 接続中&ルーム未入室状態でのOnGUI制御.
         */
        private void OnGUI_OutOfRoom()
        {
            // ロビー未入室の場合、何もしない
            if (!MonobitNetwork.inLobby)
            {
                return;
            }
            
            // ルームの作成設定
            OnGUI_CreateOrJoinRoom();
        }
        
        /**
         * ルーム作成設定.
         */
        private void OnGUI_CreateOrJoinRoom()
        {
            // 値の入力
            GUILayout.BeginHorizontal();
            GUILayout.Label("Your Rank Value(" + baseValueLow + "-" + baseValueHigh + ") : ", GUILayout.Width(200));
            baseValue = Convert.ToInt32(GUILayout.TextField(baseValue.ToString(), GUILayout.Width(50)));
            GUILayout.EndHorizontal();
            
            // ルームの作成
            if (GUILayout.Button("Create Room", GUILayout.Width(250)))
            {
                // 入力した値が範囲外の場合、入力を無視する
                if (baseValue < baseValueLow || baseValue > baseValueHigh)
                {
                    Debug.LogWarning("Your value must between" + baseValueLow + " and " + baseValueHigh);
                }
                else
                {
                    // 自身の値をクエリーパラメータとして代入
                    customRoomParam["Value"] = baseValue;
                    
                    // ロビー抽出バラメータの設定
                    string[] customRoomParametersForLobby = { "Value" };
                    
                    // ルームの作成
                    RoomSettings roomSettings = new RoomSettings()
                    {
                        isVisible = true,
                        isOpen = true,
                        maxPlayers = 0,
                        customRoomParameters = this.customRoomParam,
                        customRoomParametersForLobby = customRoomParametersForLobby
                    };
                    MonobitNetwork.CreateRoom(null, roomSettings, null);
                }
            }
            
            // ルームへの入室
            if (GUILayout.Button("Join Room", GUILayout.Width(250)))
            {
                // 入力した値が範囲外の場合、入力を無視する
                if (baseValue < baseValueLow || baseValue > baseValueHigh)
                {
                    Debug.LogWarning("Your value must between" + baseValueLow + " and " + baseValueHigh);
                }
                else
                {
                    // 自身の値に対し、検索範囲の最初の閾値を設定する
                    baseValueMin = (baseValue - baseValueIncrease < baseValueLow) ? baseValueLow : baseValue - baseValueIncrease;
                    baseValueMax = (baseValue + baseValueIncrease > baseValueHigh) ? baseValueHigh : baseValue + baseValueIncrease;
                    
                    // 閾値から、クエリー検索のためのWHERE句を生成する
                    string queryLobbyFilter = "Value>=" + baseValueMin + " AND Value<=" + baseValueMax;
                    
                    // ルームへの入室
                    MonobitNetwork.JoinRandomRoom(null, 0, Definitions.MatchmakingMode.SerialMatching, new LobbyInfo() { Kind = LobbyKind.Query, Name = "QueryLobby" }, queryLobbyFilter);
                }
            }
        }
        
        /**
         * ルーム内でのGUI操作.
         */
        private void OnGUI_InRoom()
        {
            // ルーム名の表示
            GUILayout.Label("InRoom : " + MonobitNetwork.room.name);
            
            // 部屋からの離脱
            if (GUILayout.Button("Leave Room", GUILayout.Width(150)))
            {
                MonobitNetwork.LeaveRoom();
            }
        }
        
        /**
         * サーバ接続成功時の処理.
         */
        public void OnConnectedToServer()
        {
            Debug.Log("OnConnectedToServer");
            
            // クエリーロビーに入室
            MonobitNetwork.JoinLobby(new LobbyInfo() { Kind = LobbyKind.Query, Name = "QueryLobby" });
        }
        
        /**
         * ランダム入室失敗時の処理.
         */
        public void OnMonobitRandomJoinFailed(object[] parameters)
        {
            // 閾値が限界まで達してしまった場合、そもそもルームが存在しなかった(あるいは検索中に消えた)ことになるので、エラーで抜ける。
            if (baseValueMin == baseValueLow && this.baseValueMax == baseValueHigh)
            {
                Debug.Log("OnPhotonRandomJoinFailed : ErrorCode = " + parameters[0] + ", DebugMsg = " + parameters[1]);
                return;
            }
            
            // ランダムルーム入室のクエリー検索の閾値を広げる。
            if (Mathf.Abs(baseValueMax - baseValue) <= Math.Abs(baseValueMin - baseValue))
            {
                if ((baseValueMax + baseValueIncrease) > baseValueHigh)
                {
                    baseValueMax = baseValueHigh;
                    baseValueMin = Mathf.Max(baseValueMin - baseValueIncrease, baseValueLow);
                }
                else
                {
                    baseValueMax += baseValueIncrease;
                }
            }
            else
            {
                if ((baseValueMin - baseValueIncrease) < baseValueLow)
                {
                    baseValueMin = 0;
                    baseValueMax = Mathf.Min(baseValueMax + baseValueIncrease, baseValueHigh);
                }
                else
                {
                    baseValueMin -= baseValueIncrease;
                }
            }
            
            // 閾値から、クエリー検索のためのWHERE句を生成する
            string queryLobbyFilter = "Value>=" + baseValueMin + " AND Value<=" + baseValueMax;
            
            // ルームへの入室
            MonobitNetwork.JoinRandomRoom(null, 0, Definitions.MatchmakingMode.SerialMatching, new LobbyInfo() { Kind = LobbyKind.Query, Name = "QueryLobby" }, queryLobbyFilter);
        }
    }
}


プレイヤー名検索マッチング

指定したプレイヤーの存在するルームを検出してマッチングする方法

  以下のようなスクリプトを組むことで、プレイヤー名をもとにルーム検索して、該当するルームに入室するマッチング制御が可能です。
  (簡易仕様のため、必要最低限のみの接続コールバックのみを用意し、例外処理を省いております)
using UnityEngine;
using System.Collections;

namespace MonobitEngine.Sample
{
    public class SearchPlayer : MonobitEngine.MonoBehaviour
    {
        // 自分の名前
        private string myName = "";
        
        // 検索相手の名前
        private string SearchPlayerName = "";
        
        // 検索相手の結果が得られたか?
        private bool isSearchPlayer = false;
        
        /**
         * GUI周りの制御.
         */
        public void OnGUI()
        {
            // GUI用の解像度を調整する
            Vector2 guiScreenSize = new Vector2(800, 480); // 標準解像度
            GUIUtility.ScaleAroundPivot(new Vector2(Screen.width / guiScreenSize.x, Screen.height / guiScreenSize.y), Vector2.zero);
            
            // まだ未接続の場合
            if (!MonobitNetwork.isConnect)
            {
                OnGUI_Disconnect();
            }
            // まだルーム未入室の場合
            else if (!MonobitNetwork.inRoom)
            {
                OnGUI_OutOfRoom();
            }
            // ルーム入室中の場合
            else
            {
                OnGUI_InRoom();
            }
        }
        
        /**
         * 未接続中のOnGUI制御.
         */
        public void OnGUI_Disconnect()
        {
            // 自分の名前を入力する
            GUILayout.BeginHorizontal();
            GUILayout.Label("Your Name : ");
            this.myName = GUILayout.TextField(this.myName, GUILayout.Width(200));
            GUILayout.EndHorizontal();
            
            // サーバへの接続
            if (GUILayout.Button("Connect Server", GUILayout.Width(200)))
            {
                // 空欄はNG
                if (string.IsNullOrEmpty(this.myName))
                {
                    Debug.LogWarning("Your name is null.");
                }
                else
                {
                    // プレイヤー名を設定
                    MonobitNetwork.player.name = this.myName;
                    
                    // デフォルトロビーへの強制入室をONにする
                    MonobitNetwork.autoJoinLobby = true;
                    
                    // サーバに接続する
                    MonobitNetwork.ConnectServer("SearchPlayer_v1.0");
                }
            }
        }
        
        /**
         * 接続中&ルーム未入室状態でのOnGUI制御.
         */
        private void OnGUI_OutOfRoom()
        {
            // 自分のプレイヤー名とIDを表示
            GUILayout.Label("Your Name : " + MonobitNetwork.playerName);
            
            // ルーム作成設定
            OnGUI_CreateRoom();
            
            // プレイヤー検索設定
            OnGUI_SearchPlayer();
            
            // プレイヤー検索結果の表示
            OnGUI_SearchPlayerList();
        }
        
        /**
         * ルーム作成設定.
         */
        private void OnGUI_CreateRoom()
        {
            // 表題
            GUILayout.Label("Create Room", new GUIStyle() { normal = new GUIStyleState() { textColor = Color.white }, fontStyle = FontStyle.Bold });
            GUILayout.BeginHorizontal();
            GUILayout.Space(25);
            GUILayout.BeginVertical();
            
            // 自身の名前をもとにして、ルームを作成する
            if (GUILayout.Button("Create Room", GUILayout.Width(150)))
            {
                MonobitNetwork.JoinOrCreateRoom(this.myName, new RoomSettings() { isVisible = true, isOpen = true, maxPlayers = 0 }, null);
            }
            GUILayout.EndVertical();
            GUILayout.EndHorizontal();
        }
        
        /**
         * プレイヤー検索設定.
         */
        private void OnGUI_SearchPlayer()
        {
            // 表題
            GUILayout.Label("Search Players", new GUIStyle() { normal = new GUIStyleState() { textColor = Color.white }, fontStyle = FontStyle.Bold });
            GUILayout.BeginHorizontal();
            GUILayout.Space(25);
            GUILayout.BeginVertical();
            
            // 検索するプレイヤー名を入力
            GUILayout.BeginHorizontal();
            GUILayout.Label("Player Name : ");
            this.SearchPlayerName = GUILayout.TextField(this.SearchPlayerName, GUILayout.Width(200));
            // プレイヤーを検索する
            if (GUILayout.Button("Search", GUILayout.Width(150)))
            {
                // 空欄はNG
                if (string.IsNullOrEmpty(this.myName))
                {
                    Debug.LogWarning("Player name is null.");
                }
                else
                {
                    // プレイヤー検索は時間がかかるので、コルーチンで実行する
                    StartCoroutine("SearchPlayerList");
                }
            }
            GUILayout.EndHorizontal();
            
            GUILayout.EndVertical();
            GUILayout.EndHorizontal();
        }
        
        /**
         * プレイヤー検索結果の表示.
         */
        private void OnGUI_SearchPlayerList()
        {
            // プレイヤーが見つかっていない場合には処理しない
            if (!isSearchPlayer)
            {
                return;
            }
            
            // 表題
            GUILayout.Label("Search Player List", new GUIStyle() { normal = new GUIStyleState() { textColor = Color.white }, fontStyle = FontStyle.Bold });
            GUILayout.BeginHorizontal();
            GUILayout.Space(50);
            GUILayout.BeginVertical();
            
            // 検索できたプレイヤーの分だけ表示する
            foreach (SearchPlayerData player in MonobitNetwork.SearchPlayerList)
            {
                if (!player.connect)
                {
                    // オフライン(ユーザーが存在しない)
                    GUILayout.Label(player.playerName + " is offline.");
                }
                else if (!player.inRoom)
                {
                    // ルーム未入室
                    GUILayout.Label(player.playerName + " is out of rooms.");
                }
                else
                {
                    // ルーム入室中
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(player.playerName + " is in " + player.roomName, GUILayout.Width(250));
                    // 選択したプレイヤーの部屋に入室
                    if (GUILayout.Button("Join", GUILayout.Width(50)))
                    {
                        MonobitNetwork.JoinRoom(player.roomName);
                    }
                    GUILayout.EndHorizontal();
                }
            }
            
            GUILayout.EndVertical();
            GUILayout.EndHorizontal();
        }
        
        /**
         * フレンド検索.
         */
        private IEnumerator SearchPlayerList()
        {
            // フラグをクリア
            isSearchPlayer = false;
            
            // プレイヤー検索リストの作成
            string[] searchList = this.SearchPlayerName.Split(' ');
            
            // フレンドの検索
            MonobitNetwork.SearchPlayers(searchList);
            
            // 見つかるまで待つ
            while (!isSearchPlayer)
            {
                yield return null;
            }
        }
        
        /**
         * ルーム内でのGUI操作.
         */
        private void OnGUI_InRoom()
        {
            // 自分の名前とプレイヤーIDの表示
            GUILayout.Label("InRoom : " + MonobitNetwork.room.name);
            
            // 部屋からの離脱
            if (GUILayout.Button("Leave Room", GUILayout.Width(100)))
            {
                MonobitNetwork.LeaveRoom();
            }
        }
        /**
         * プレイヤー検索結果が返ってきた時の処理.
         */
        public void OnUpdatedSearchPlayers()
        {
            Debug.Log("OnUpdateFriendList");
            isSearchPlayer = true;
        }
    }
}