リアルタイム通信パッケージ for Unity
majiXAは、リアルタイム通信ゲームを開発することが出来るパッケージです。
nginx-luajit-wsをベースにUnity上で開発をしやすくしたものです。
言語はC#です。
majiXAはクライアント同士をP2Pで接続するのではなく、サーバを介して各クライアントにデータを送受信する形を採用しています。
ゲームをサーバで動かすことで、クライアントAが通信切断したとしても、クライアントBはゲームを続行することができます。
- Unity 2017以降
- CentOS 7
- Ubuntu
- Unity上で新規プロジェクトを作成します
- unitypackage/majiXA_1.0.0.unitypackageをImportします
- WebuSocketをダウンロードして解凍します。
- WebuSocket-0.8.0/WebuSocketフォルダを、1.で作ったプロジェクトのAssets/majiXA/Client/以下にコピーします。
- Disquuunをダウンロードして解凍します。
- Disquuun-0.6.0/Disquuunフォルダを、1.で作ったプロジェクトのAssets/majiXA/Server/Editor/以下にコピーします。
※ Macの方は、setup.shをプロジェクトフォルダ(1.で作成したプロジェクトのフォルダ)に配置して実行することで 3〜6 の工程を自動で行えます。
サンプルを使って動作確認をします。
- unitypackage/sample.unitypackageをImportします
- Assets/Sample/からSampleシーンを開きます。
- majiXA/Configs/Config.csのBUNDLE_IDENTIFIERをユニークなバンドルIDに書き換えます。
これでサンプルの準備は完了です。
以下から動作確認をします。
- Unityから再生します。
- メニューからmajiXA > Local Server Controller を選択してウィンドウを表示します。
- LocalServerCtrl(以後LSC)の「Start」ボタンを押します。接続プレイヤー数とルーム数が表示されます。
- Game画面内の「Connect to Server」ボタンを押します。
- LSCの接続プレイヤー数が1になったことを確認します。
- Game画面内の「Room Join」ボタンを押します。
- LSCのルーム数が1になったことを確認します。
- Game画面内の「ResponseNumber」ボタンを押します。
- Game画面内に「Get Number XX(ランダムな数字)」が表示されることを確認します。
- Game画面内の「Room Leave」ボタンを押します。
- LSCのルーム数が0になったことを確認します。
- Game画面内の「Disconnect」ボタンを押します。
- LSCの接続プレイヤー数が0になったことを確認します。
- Unityの再生を終了します。
この一連の流れが動作すれば正しく動いています。
ここではLinuxサーバ(centos or ubuntu)を使用します。
(以下のコマンドはcentosでの説明になります)
- Linuxサーバを構築します。
- dockerをインストールします。
yum install docker
- dockerを起動
systemctl start docker
- nginx-luajit-wsをダウンロードして解凍します。
- cd nginx-luajit-ws-benchmark-with-netcore
- DockerResources/nginx.confの62行目、63行目の
sample_disque_client
をdisque_client
に書き換えます。(sample_を削除する) - DockerResources/lua/sample_disque_client.luaのファイル名をdisque_client.luaに書き換えます。
- nginx-luajit-ws-benchmark-with-netcore/c_rebuild.shを実行します。
docker ps
でnginx_luajitが起動していれば成功です。
サーバ側のプログラムを配置します。
- DotNetCoreをインストールします。
- サーバプログラムに必要なプログラムを配置します。
Program.cs
majixa.csproj
Assets/majiXA/ClientAndServer/*
Assets/majiXA/Configs/Editor/*
Assets/majiXA/Server/Editor/*
その他プロジェクトで追加したサーバ側プログラム - ビルド
dotnet build
- 実行
dotnet run
majiXA内の設定ファイルをいくつか修正する必要があります。
- majiXA/ClientAndServer/Commands.cs
- ProcessingNameSpace
サーバ側の処理(IProcessingを継承したクラス)でnamespaceを使用する際はそのnamespaceを記述 - eCom
各種コマンドを設定
- ProcessingNameSpace
- majiXA/Configs/Editor/Server.cs
- DISQUE_HOST_IP
- DISQUE_PORT
接続先DisqueのIPとポートを設定します。
IPアドレスとポートを指定します。
Config.Common.BUNDLE_IDENTIFIERを、ユニークな文字列になるように変更する必要があります。
using majiXA;
void Start()
{
WebuSocketController ws = new WebuSocketController();
ws.Connect("111.222.333.444:8080", Config.Common.BUNDLE_IDENTIFIER);
}
ws.Close();
クライアントからサーバに対してデータを送信する方法
最初の1byte目には、必ずeCommandに設定した値を入れる必要があります。
// 例えばXXXというコマンド(コマンドはmajiXA/ClientAndServer/Commands.csに記述)でfooというintを送りたい時
int foo = 1;
List<byte> data = new List<byte>();
data.Add((byte)eCommand.XXX);
data.AddRange(foo.ToBytes());
ws.Send(data.ToArray());
// これでコマンドが1byte、fooがintなので4byte、計5byteのデータを送信します。
byte配列を引数に持つ ReceiveXXX(名前は任意) を作成して、receiveActionDictに登録します。
こうしておく事でサーバからeCommand.XXXのコマンドでデータが届いた場合、ReceiveXXXが呼ばれます。
void Start()
{
ws.receiveActionDict.Add((byte)eCommands.XXX, ReceiveXXX);
}
void ReceiveXXX(byte[] ret)
{
...
}
- OnUpdate()は毎ループ呼ばれます。
- Joinは、このRoomに入室する際に呼びます。
- Leaveは、このRoomから退室する際に呼びます。
public class Room : IRoom
{
public void OnUpdate()
{
// 毎ループ実行される(60fps なら 1秒 に 60回 実行される)
}
public int Join(ConnectionInfo cInfo)
{
// プレイヤーがルームに入室する際に呼ばれます
}
public int Leave(ConnectionInfo cInfo)
{
// プレイヤーがルームから退室する際に呼ばれます
}
}
majiXA/ClientAndServer/Commands.cs
public enum eCommand : int {
XXX, // <= 任意の名前のコマンドを追記
}
- OnMessageはclass名のコマンドがクライアントから送信されてきた際に呼ばれます。
public class XXX : IProcessing
{
public void OnMessage(ServerContext context, ConnectionInfo cInfo, byte[] data)
{
// cInfo にはデータを送信してきたプレイヤーの情報が入っています。
// data はクライアント (ws.Send(data.ToArray()) から送られてきたbyte配列
}
}
このソフトウェアは、MITライセンスのもとで公開されています。(LICENSE.txt)