チャットルーム内の制御

目次

  概要
  ルーム内のプレイヤー一覧の取得
  RPCによる情報の送信
  RPCによる情報の受信
  受信した情報の表示
  ここまでのChatScriptの内容


概要

チャットルーム内の機能を作ってみる

  ここではチャットルーム内での各種制御について、MUN クライアントの主要機能に触れながら組み込んでみましょう。


ルーム内のプレイヤー一覧の取得

ルーム内のプレイヤー一覧を表示する

  ChatScript の 22 行目付近から、以下のコードを記述します。
				// ルーム内のプレイヤー一覧の表示
				GUILayout.BeginHorizontal();
				GUILayout.Label("PlayerList : ");
				foreach(MonobitPlayer player in MonobitNetwork.playerList)
				{
					GUILayout.Label(player.name + " ");
				}
				GUILayout.EndHorizontal();
  MonobitNetwork.playerList は、現在入室しているルーム内に存在するプレイヤーについて、その一覧を配列情報で格納されています。

  データ型は MonobitPlayer[] 型で、上記の例では foreach() にて要素を1つずつ player に取得し、
  その中に含まれる MonobitPlayer.name を使って「プレイヤー名の一覧」を表示させています。


RPCによる情報の送信

チャット発言文を保持する変数を宣言する

  ChatScript の 11 行目付近から、以下のコードを記述します。
	/** チャット発言文. */
	private string chatWord = "";
	
  GUIを使って入力するチャット発言文を保持する、string 型の変数を用意します。

チャットGUIを作成する

  ChatScript の 34 行目付近から、以下のコードを記述します。
				// チャット発言文の入力
				GUILayout.BeginHorizontal();
				GUILayout.Label("Message : ");
				chatWord = GUILayout.TextField(chatWord, GUILayout.Width(400));
				GUILayout.EndHorizontal();
	
  前述までと同様、Unityで通常用いる GUILayout を使ってチャット発言文の入力処理を行ないます。

チャット発言文を送信する

  ChatScript の 40 行目付近から、以下のコードを記述します。
                // チャット発言文を送信する
                if (GUILayout.Button("Send", GUILayout.Width(100)))
                {
                    monobitView.RPC("RecvChat",
                                    MonobitTargets.All,
                                    MonobitNetwork.playerName,
                                    chatWord);
                    chatWord = "";
                }
  [Send] ボタンを押したときに、RPCを使ってメッセージを送信します。
  RPC については こちら を御参照ください。

  今章の最初に追加された MonobitViewコンポーネント を用いて、MonobitView.RPC() メソッドをコールします。
  (ソース内に記された monobitView は、MonobitViewコンポーネント本体を取得するプロパティです。)

  MonobitView.RPC() メソッドにより、ルーム内のすべてのクライアントに対して、
    ・ MonobitNetwork.playerName - 自身のプレイヤー名
    ・ chatWord - チャット会話文として入力した文字列
  を送信します。


RPCによる情報の受信

System.Collections.Generic の using ディレクティブを追加する

  Unity2018.2 以下のバージョンをお使いの場合、ChatScript の 2 行目付近に、以下のコードを記述します。
  (Unity2018.3 以降であればすでに含まれていますので、書いても書かなくとも構いません)
using System.Collections.Generic;
  後述の発言ログ(List<T>)を利用するための using ディレクティブを追加します。

チャット発言ログを保持する変数を宣言する

  さらに ChatScript の 14 行目付近から、以下のコードを記述します。
	/** チャット発言ログ. */
	List<string> chatLog = new List<string>();
	
  GUIを使って入力するチャット発言ログを保持する、List<string> 型の変数を用意します。

チャット発言文を受信し、発言ログに追加する

  ChatScript の 17 行目付近から、以下のコードを記述します。
	/**
	 * RPC 受信関数.
	 */
	[MunRPC]
	void RecvChat(string senderName, string senderWord)
	{
		chatLog.Add(senderName + " : " + senderWord);
		if( chatLog.Count > 10 )
		{
			chatLog.RemoveAt(0);
		}
	}
 
  MonobitView.RPC() メソッドを使って送信された情報の受信メソッドを定義します。
  このメソッドの定義要件は以下の通りです。
・メソッド名の接頭に[MunRPC]のアトリビュートを付記すること。
・MonobitView.RPC() メソッド の第1引数と同じ名前のメソッド名で定義すること。
・MonobitView.RPC() メソッド の第3引数以降に対応するデータ型の引数値を定義すること。
  今回の場合、MonobitView.RPC() メソッド の第1引数に "RecvChat" を指定していましたので、 メソッド名を RecvChat() として定義します。
  また、MonobitView.RPC() メソッド の第3引数以降に ( string, string ) 型のデータを指定していますので、
  RecvChat() の引数値も (string, string) のデータ型で一致させます。

  処理内で行なっていることは、至って単純で、"送信者名 : 送信文書"の形式で chatLogに後方追加し、
  chatLog に追加された件数が10件を超えたら、List の先頭を削除する、という処理を行なわせます。


受信した情報の表示

chatLog の内容を表示する

  ChatScript の 67 行目付近から、以下のコードを記述します。
				// チャットログを表示する
				string msg = "";
				for(int i = 0; i < 10; ++i )
				{
					msg += ((i < chatLog.Count) ? chatLog[i] : "") + "\r\n";
				}
				GUILayout.TextArea(msg);
  chatLog を msg にまとめ、GUILayout.TextArea() で表示させます。


ここまでのChatScriptの内容


  改めて触れますが、ここまでのChatScript.cs の内容は以下の通りです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MonobitEngine;

public class ChatScript : MonobitEngine.MonoBehaviour
{
    /** ルーム名. */
    private string roomName = "";

    /** チャット発言文. */
    private string chatWord = "";

    /** チャット発言ログ. */
    List<string> chatLog = new List<string>();

    /**
     * RPC 受信関数.
     */
    [MunRPC]
    void RecvChat(string senderName, string senderWord)
    {
        chatLog.Add(senderName + " : " + senderWord);
        if (chatLog.Count > 10)
        {
            chatLog.RemoveAt(0);
        }
    }

    /**
     * GUI制御.
     */
    void OnGUI()
    {
        // MUNサーバに接続している場合
        if (MonobitNetwork.isConnect)
        {
            // ルームに入室している場合
            if (MonobitNetwork.inRoom)
            {
                // ルーム内のプレイヤー一覧の表示
                GUILayout.BeginHorizontal();
                GUILayout.Label("PlayerList : ");
                foreach (MonobitPlayer player in MonobitNetwork.playerList)
                {
                    GUILayout.Label(player.name + " ");
                }
                GUILayout.EndHorizontal();

                // チャット発言文の入力
                GUILayout.BeginHorizontal();
                GUILayout.Label("Message : ");
                chatWord = GUILayout.TextField(chatWord, GUILayout.Width(400));
                GUILayout.EndHorizontal();

                // チャット発言文を送信する
                if (GUILayout.Button("Send", GUILayout.Width(100)))
                {
                    monobitView.RPC("RecvChat",
                                    MonobitTargets.All,
                                    MonobitNetwork.playerName,
                                    chatWord);
                    chatWord = "";
                }

                // チャットログを表示する
                string msg = "";
                for (int i = 0; i < 10; ++i)
                {
                    msg += ((i < chatLog.Count) ? chatLog[i] : "") + "\r\n";
                }
                GUILayout.TextArea(msg);
            }
            // ルームに入室していない場合
            else
            {
                // ルーム名の入力
                GUILayout.BeginHorizontal();
                GUILayout.Label("RoomName : ");
                roomName = GUILayout.TextField(roomName, GUILayout.Width(200));
                GUILayout.EndHorizontal();

                // ルームを作成して入室する
                if (GUILayout.Button("Create Room", GUILayout.Width(150)))
                {
                    MonobitNetwork.CreateRoom(roomName);
                }

                // ルーム一覧を検索
                foreach (RoomData room in MonobitNetwork.GetRoomData())
                {
                    // ルームパラメータの可視化
                    System.String roomParam =
                        System.String.Format(
                            "{0}({1}/{2})",
                            room.name,
                            room.playerCount,
                            ((room.maxPlayers == 0) ? "-" : room.maxPlayers.ToString())
                        );

                    // ルームを選択して入室する
                    if (GUILayout.Button("Enter Room : " + roomParam))
                    {
                        MonobitNetwork.JoinRoom(room.name);
                    }
                }
            }
        }
        // MUNサーバに接続していない場合
        else
        {
            // プレイヤー名の入力
            GUILayout.BeginHorizontal();
            GUILayout.Label("PlayerName : ");
            MonobitNetwork.playerName = GUILayout.TextField(
                (MonobitNetwork.playerName == null) ?
                    "" :
                    MonobitNetwork.playerName, GUILayout.Width(200));
            GUILayout.EndHorizontal();

            // デフォルトロビーへの自動入室を許可する
            MonobitNetwork.autoJoinLobby = true;

            // MUNサーバに接続する
            if (GUILayout.Button("Connect Server", GUILayout.Width(150)))
            {
                MonobitNetwork.ConnectServer("SimpleChat_v1.0");
            }
        }
    }
}