サーバサイドプログラムの事前構築

目次

  概要
  現時点でリリースしているMUNサーバについて、サーバサイドプログラムを行なう上での制約
  サーバサイドプログラムを実装するためのソースファイルを作成する
  ソースファイルのテンプレートを組み込む
  テンプレートに関する解説
  ルーム開設時にサーバサイドプログラムが起動するようにする


概要

サーバサイドプログラミングの環境構築

  ここでは、サーバサイドプログラミングを行なう上で、あらかじめ「行なっておいた方が良い」と思われる事前構築について説明します。

  説明する内容について簡単に要約すると、弊社で提供している MUN サーバ側の公開コードと、お客様にてこれから組み込まれる
  サーバサイドプログラムの実装部分について分離しておく作業の説明です。

  これ自体は必須ではありませんが、カスタム認証とは違い、こちらは今後バージョンアップに伴う小中規模の仕様変更がなされる
  可能性が高いため、バージョンアップ対応のために「行っておいた方が良い」と判断いたします。

  できるだけ、この事前構築を行なったうえで組み込んでおいてください。


現時点でリリースしているMUNサーバについて、サーバサイドプログラムを行なう上での制約

サーバサイドプログラム実装における、現時点での制約内容

  事前構築を行なう前に、現時点でリリースしているサーバサイドプログラムについて、制約内容を提示します。

制約[1] : Unityプログラマの方が部分的にカスタマイズをする事を想定しC# 版のみ対応しています(C++版は今後リリース予定です)

  現時点でリリースしているサーバサイドプログラムの実装上では、
  C# 版(Windows 環境)のみ対応しており、C++ 版はまだ未対応の状態です。

  これにつきましては、早急に C++ 版に対応してリリースする予定ですので、
  しばらくの間お待ちいただければと思います。

制約[2] : mun_room サーバプロセスのみ対応しています

  現時点でリリースしているサーバサイドプログラムの実装上では、
  mun_room サーバプロセスのみ対応しております。
  mun_master/mun_resolver/mun_proxy のサーバプロセスについては、同様の内容を組み込むことができません。

  これにつきましては、MUNのサーバプログラム群は互いに密結合となっており、
  mun_room以外のサーバプログラムをカスタマイズしようとすると、   難易度がかなり上がってしまい、動作の保証がし辛くなってしまいます。
  更にマッチングやルーム管理周りのカスタマイズはかなりの大改造になってしまうという理由から
  現時点ではプログラムパッケージのリリースとして対応する予定にはありません。

    ※ 例えば、ロビー内のに空ルームを常設し、限られたルーム/限られたルーム内プレイヤーにてマッチングさせるなど、
      mun_room 以外にサーバプログラムをカスタマイズするケースは様々考えられますが、
      こういったケースについては、今回取り上げる「サーバサイドプログラム」とは別カテゴリにて、
      当技術文書ページにてご案内させていただく予定です。

  こちらもドキュメントリリースまで、しばらくお待ちいただければと思います。


サーバサイドプログラムを実装するためのソースファイルを作成する

各種プラットフォーム向けの、mun_room サーバのプロジェクトファイルに、新規ソースファイルを追加する

  では、サーバサイドプログラムの事前構築について、順を追って解説していきます。
  まずは、mun_room サーバプロセスに対して、サーバサイドプログラムを実装するための新規ソースファイルを追加します。

  下記のうち、ご利用されている MUN サーバのプラットフォームに合わせて、カーソルクリックしてください。

1. 頒布している MUN サーバパッケージの解凍先ディレクトリ内の server/csharp/mun_room ディレクトリを開きます。
2. ご利用される OS のCPUアーキテクチャ、および VisualStudio のバージョンに合わせて、以下のソリューションファイルを開いてください。
server
  └ csharp
    └ mun_room
        ├ mun_room_vs2010_Win32.sln … VisualStudio 2010 で動作させる場合(32bitOS, 64bitOSを問わず)
        ├ mun_room_vs2012_Win32.sln … VisualStudio 2012 + 32bitOS で動作させる場合
        ├ mun_room_vs2012_x64.sln  … VisualStudio 2012 + 64bitOS で動作させる場合
        ├ mun_room_vs2013_Win32.sln … VisualStudio 2013 + 32bitOS で動作させる場合
        ├ mun_room_vs2013_x64.sln  … VisualStudio 2013 + 64bitOS で動作させる場合
        ├ mun_room_vs2015_Win32.sln … VisualStudio 2015 + 32bitOS で動作させる場合
        └ mun_room_vs2015_x64.sln  … VisualStudio 2015 + 64bitOS で動作させる場合
3. Visual Studio でソリューションファイルを開いた後、ソリューションエクスプローラーから、
  mun_room プロジェクト内の src/database ディレクトリを展開し、その中に適切な名前のディレクトリを作成します。
   ※ 以下は、「Custom」という名前でディレクトリを作成した例です。
4. 更に上記で作成したディレクトリ内に、適切な名前の C# スクリプトファイルを作成します。
   ※ 以下は、「MunRoomOperation.cs」という名前でファイルを作成した例です。


ソースファイルのテンプレートを組み込む

追加した新規ソースファイルに対し、雛形を組み込む

  上記手順で作成した新規ソースファイルについて、サーバサイドプログラムを組み込むための雛形を作成します。

  下記のうち、ご利用されている MUN サーバの開発言語に合わせて、カーソルクリックしてください。
C# 版 MUN サーバの場合、 mun_room に組み込むサーバサイドプログラムの最初の雛形は以下の通りです。
  ※ <任意の名前空間名> および <任意のクラス名>の箇所には、適宜適切な名前を設定してください。
using System;

namespace <任意の名前空間名>
{
    class <任意のクラス名> : MonobitEngine.MonoBehaviour
    {
        /**
         * @brief   作成されたルーム情報.
         */
        MunRoomInfo m_RoomInfo = null;

        /**
         * @brief   コンストラクタ.
         * @param   roomInfo    作成されたルーム情報.
         */
        public <任意のクラス名>(MunRoomInfo roomInfo)
        {
            // 自身のクラスを MonobitNetwork の監視下に登録する
            MonobitEngine.MonobitNetwork.AddBehaviour(roomInfo.GetId(), this);

            // ルーム情報を退避
            m_RoomInfo = roomInfo;
        }

        /**
         * @brief   デストラクタ.
         */
        ~<任意のクラス名>()
        {
            // 自身のクラスを MonobitNetwork の監視下から除外する
            MonobitEngine.MonobitNetwork.RemoveBehaviour(this);
        }

        /**
         * @brief   ルーム作成時の処理.
         */
        public override void Start()
        {
            // TODO : ルーム作成時の処理
        }

        /**
         * @brief   ルーム更新時の処理.
         */
        public override void Update()
        {
            // TODO : ルーム更新時の処理
        }

        /**
         * @brief   MUN サーバからリクエスト送信されたシーンオブジェクトが MUN クライアント上に生成された時のコールバック.
         * @param   prefabName      生成されたシーンオブジェクトのプレハブ名.
         * @param   position        生成されたシーンオブジェクトの位置.
         * @param   rotation        生成されたシーンオブジェクトの向き.
         * @param   viewId          生成されたシーンオブジェクトのMonobitViewID.
         */
        public void OnMonobitInstantiateSceneObject(string prefabName, MonobitEngine.UnityEngine_Vector3 position, MonobitEngine.UnityEngine_Quaternion rotation, Int32 viewId)
        {
            // TODO : MUN サーバからリクエスト送信されたシーンオブジェクトが MUN クライアント上に生成された時の処理
        }

        /**
         * @brief   MUN クライアントから オブジェクト同期データが送信されてきた時のコールバック.
         * @param   playerId        送信者であるプレイヤーの ID.
         * @param   viewId          送信オブジェクトが保持する MonobitView の ID.
         * @param   objectName      送信オブジェクトのGameObjectの名前.
         * @param   transData       MonobitTransformView コンポーネントから送信されてきたデータ群.
         * @param   animData        MonobitAnimatorView コンポーネントから送信されてきたデータ群.
         * @param   otherData       MonobitTransformView コンポーネント、および MonobitAnimatorView コンポーネント以外から送信されてきたデータ群。
         *                          このデータで送信されてくるデータには、Transform, Rigidbody, および OnMonobitSerializeView() メソッドで送られるストリーム情報がある.
         */
        public void OnMonobitSerializeView(Int32 playerId, Int32 viewId, string objectName, object[] transData, object[] animData, object[] otherData)
        {
            // TODO : MUN クライアントから オブジェクト同期データが送信されてきた時の処理
        }
    }
}

なお、上述の例(src/database/Custom/MunRoomOperation.cs)の場合には、以下のようにコードを記述します。


テンプレートに関する解説

サーバサイドプログラムの雛形に関する、簡単なロジックの説明

  上記で組み込みしている雛形について、簡略的に解説を行ないます。

MUN クライアント接続直後の認証要求を受信した場合の処理

  MUN クライアントがmun_proxy サーバに接続した後、認証要求のプロセスに入ります。
  このとき、mun_proxy サーバ側で Recv_Proxy_Check() のメソッド(関数)が実行され、認証処理が行われます。

  下記のうち、ご利用されている MUN サーバの開発言語に合わせて、カーソルクリックしてください。
コンストラクタ、およびデストラクタは、以下のように定義されます。

コンストラクタはルーム作成時に、作成されたルーム情報をパラメータとして呼び出されます(呼び出し部分については後ほど追加します)。
コンストラクタでは、MUN サーバ向けに作成された MonobitNetwork を利用できるように、
MonobitNetwork.AddBehaviour() を使って、自身のクラスオブジェクトの登録を行ないます。

一方、デストラクタはルームが消失した時に自動的に呼び出されます。
デストラクタでは、コンストラクタで登録した MonobitNetwork の監視対象から外すため、
MonobitNetwork.RemoveBahaviour() を使って、自身のクラスオブジェクトの抹消を行ないます。
Start() メソッドは、以下のように定義されます。
MUN サーバ向けに用意された MonobitEngine.MonoBehaviour の抽象メソッドをオーバーライドして使用しますので、
「override」の接頭辞が必要です。
Start() メソッドは、コンストラクタから呼び出されます。

機能としては、UnityEngine.MonoBehaviour(およびMonobitEngine.MonoBehaviour)で利用される
Start() 関数と同等の機能を持たせます。(互換であることを認識できるように、同一のメソッド名として用意しています。)

ここで、ルーム作成時、提供されるサービスに応じて適宜「ルーム作成時の処理」を記述することになります。
Update() メソッドは、以下のように定義されます。
MUN サーバ向けに用意された MonobitEngine.MonoBehaviour の抽象メソッドをオーバーライドして使用しますので、
「override」の接頭辞が必要です。

Update() メソッドは、MonobitNetwork.AddBehaviour() によって登録されたクラスオブジェクトに対し、
一定のタイミング(現状ではおおよそ1ミリ秒間隔)で自動的に呼び出されます。

機能としては、UnityEngine.MonoBehaviour(およびMonobitEngine.MonoBehaviour)で利用される
Update() 関数と同等の機能を持たせます。(互換であることを認識できるように、同一のメソッド名として用意しています。)

ここで、提供されるサービスに応じて、ルームが稼働中に行なわれる各種イベント制御について
適宜、「ルーム更新時の処理」を記述することになります。
OnMonobitInstantiateSceneObject() メソッドは、以下のように定義されます。

このメソッドは、後述する
  「MUN サーバから MUN クライアント向けに、prefab データから『シーン内の静的オブジェクト』として生成するリクエスト」
を出した後で、正常にに MUN クライアントによって静的オブジェクトが生成されたのを受けてコールバックされるメソッドです。

後ほど改めて説明いたしますが、このメソッドは以下のパラメータを持ちます。
変数名 内容
string prefabName 生成されたシーンオブジェクトのプレハブ名。(≠ゲームオブジェクト名)
一般的に prefab を Instantiate で実体化した場合、ゲームオブジェクト名は「prefab名+(Clone)」となりますが、
ここで取得できるのはあくまで「プレハブ名」のため、「(Clone)」は付きません。
MonobitEngine.UnityEngine_Vector3 position 生成されたシーンオブジェクトの座標値。
MonobitEngine.UnityEngine_Vector3 は UnityEngine.Vector3 と同じデータ型を持ちます。
ただし、算出等を行なうためのメソッドは一切用意していません。
MonobitEnigne.UnityEngine_Quaternion rotation 生成されたシーンオブジェクトの姿勢・角度。
MonobitEngine.UnityEngine_Quaternion は UnityEngine.Quaternion と同じデータ型を持ちます。
ただし、算出等を行なうためのメソッドは一切用意していません。
Int32 viewId 生成されたシーンオブジェクトが持つ、MonobitView の ID。
MUN の仕様上、この値は 1~ 999 のうちのいずれかの値を取ります。
ここで取得できた座標や角度などから、MUNサーバ側で「シーンオブジェクトの初期位置」を導き出します。
また、ここで取得できた情報を退避することにより、Update() メソッドによる、例えばNPCの移動などのフレーム制御を実現することができます。
OnMonobitSerializeView() メソッドは、以下のように定義されます。

このメソッドは、MUN クライアント内に存在する「クライアント自身が所有権を持つ MonobitView コンポーネントがアタッチされたオブジェクト」について、
オブジェクト同期データが送信されてきたのを受けてコールバックされるメソッドです。

これも後ほど改めて説明いたしますが、このメソッドは以下のパラメータを持ちます。
変数名 内容
Int32 playerId そのオブジェクトの所有権を持ち、かつ、オブジェクト同期データを送信してきた、
ルーム内プレイヤーに割り当てられた、MonobitPlayer の ID。
Int32 viewId クライアント自身が所有権を持つオブジェクトが有する、MonobitView の ID。
MUN の仕様上、この値は (playerId の値 × 1000) + (0~ 999) のうちのいずれかの値を取ります。
string objectName ゲームシーン上に登録されたゲームオブジェクトの名前。(≠プレハブ名)
一般的な例を挙げれば、prefab を Instantiate で実体化した場合、ゲームオブジェクト名は「prefab名+(Clone)」となりますが、
その場合、その名前がそのままこのパラメータに入ります。
そのため、必ずしも「プレハブ名」と同一にはなりません。
object[] transData MonobitTransformView コンポーネントを使い、MUNクライアントから送信されてきたオブジェクト同期データ。
このデータには、同期データとして送信される情報のうち、位置(position)・姿勢(rotation)・倍率(scale)を含んでいます。
具体的にどんなデータが送られてくるかは、該当するゲームオブジェクトの
MonobitTransformView コンポーネント に登録されている送信設定に依存します。
object[] animData MonobitAnimatorView コンポーネントを使い、MUNクライアントから送信されてきたオブジェクト同期データ。
このデータには、同期データとして送信される情報のうち、アニメーションのフラグ、アニメーション変数を含んでいます。
具体的にどんなデータが送られてくるかは、該当するゲームオブジェクトの AnimationController の状態、
ならびに、MonobitAnimatorView コンポーネント に登録されている送信設定に依存します。
object[] otherData transData, animData を除く、MUN クライアントから送信されてきたオブジェクト同期データ。
このデータには、同期データとして送信される情報のうち、Transforrm, Rigidbody のコンポーネント、あるいは
OnMonobitSerializeView() メソッドを使って送信されてきたものを含んでいます。
具体的にどんなデータが送られてくるかは、MonobitView の Observed Component List への登録順や登録内容、
ならびに、OnMonobitSerializeView() メソッドを使って送信されてくるストリームの順番・登録内容に依存します。
ここで取得できた座標や角度などから、MUNサーバ側で「クライアントが所有権を持つオブジェクトの位置情報」を導き出します。
また、ここで取得できた情報を退避することにより、Update() メソッドによる、例えば衝突判定などの判定監視やゲームルールの運用制御を実現することができます。


ルーム開設時にサーバサイドプログラムが起動するようにする

新規追加したソースファイルの内容が、ルームごとに個別動作するように、既存のサーバプログラムにコードを追加する

  上記で追加したソースファイルの内容について、ルーム開設時に、ルームごとに個別動作するように、既存のサーバプログラムに手を加えます。

  下記のうち、ご利用されている MUN サーバの開発言語に合わせて、カーソルクリックしてください。
1. mun_room プロジェクト内の src/database/Room ディレクトリ内にある MunRoomInfo.cs を開きます。

2. MunRoomInfo クラスに、上記で作成したテンプレートクラスのフィールドを追加します。
   ※ 以下は上述までの例に従ったものであり、実際に追加される場合には、
     自身が追加した名前空間名、およびクラス名に応じて、適宜変更してください。

3. この上で、MunRoomInfo クラスのコンストラクタにて、上記フィールドのインスタンスを生成します。
  コンストラクタのパラメータには、MunRoomInfo のコンストラクタの引数 id をそのまま設定してください。