4
2

More than 3 years have passed since last update.

UnityでProtocolBuffersを使ってみましょう。

Last updated at Posted at 2020-04-22

こんばんは。組込みエンジニアの人です。
趣味で、Unityにて、MO系のゲームを作ろうとした際に、ProtocolBuffersを採用しようと思ったのですが、環境構築に嵌ってしまったのと、まとまった情報が無かったので、メモ書き程度に残します。

Protocol Buffersとは

下記、記事が分かりやすかったです。本ページでは説明を省略します。
ProtocolBuffersについて調べてみた

なぜ、バイナリデータを使うか?

オンラインゲームでは、特に短い間隔でソケット通信を行うとします。
例えば、10[ms]感覚で256[byte]のテキストデータを送るとします。

クライアント⇒サーバへ1[s]送る回線データは、256[byte] * ( 1000[ms] / 10[ms]) = 256,000[byte]とします。

これがクライアントが100台あった場合、256,000[byte] * 100[台] = 256,000,000[byte]
つまり、1秒間に256[MB]の回線データが飛ぶことになります。
サーバ⇒クライアントから返すデータ等を加味するともっと増えますね。

Protocol-Buffersは、テキストデータをバイナリデータに変換することで、データのサイズを圧縮することが可能です。
例えば、先ほどの例のテキストデータを圧縮することで128[byte]になったのであれば、それだけで使用する回線データは半分に削減できます。

こうすることで、変換する処理はクライアント⇔サーバで負荷は増えるのですが、通信帯域を圧迫せずに済みます。

ProtoBuf-netとGoogle.ProtoBufの違い

実装を進めていく中で、2つC#のライブラリがあることが分かりました。
ざっくりと説明すると、
protobuf-netは、ProtocolBuffers の非公式 C# 実装。
Google.ProtoBufは、ProtocolBuffers の公式 C# 実装。
です。

Google.ProtoBufは、依存関係が複雑なのか、単体で、.dllを読込むとエラーとなるため、
今回は、protobuf-netを使います。ProtocolBuffersの規格は決まっているおり、
圧縮したいという目的は達成できるため、どちらでも、よいと判断しました。

Unityに導入する手順

1. proto-buf-netのダウンロード

下記のサイトより、Download packageにて、ダウンロードします。
拡張子が.nugetになっているので、.zipに直して、解凍してください。
執筆時のバージョンは、2.4.6を使用しました。

解凍をすると、protobuf-net.2.4.6\lib\net20の中に、protobuf-net.dllがあると思います。

キャプチャ.PNG

2. .protoファイルのコンパイル

下記のように.protoファイルを作ります。
文法については、公式サイトを参照お願いします。

example.proto
syntax = "proto3";
package moprotocol;

message MOProtocol {
    string msgID = 1;
    map<string, string> data = 2;
}

コンパイルについては、protogen.exeを使うことも出来るのですが、ブラウザ上で、コンパイルできるサービスを見つけました。
https://protogen.marcgravell.com/

protogenのC#を選択した状態で、上記のコードをコピーし、Generateボタンを押してください。

キャプチャ2.PNG

下の画面上に、ソースコードが出てきます。それをUnity上で使うので、MOProtocol.csとして保存してください。
キャプチャ3.PNG

3.Unity上にライブラリを入れる。

Unityを起動し、適当にプロジェクトを起動してください。

最初にprotobuf-net.dllをAssets/Plugins上に入れてください。
キャプチャ4.PNG

次に、先ほど作成したMOProtocol.csを任意のフォルダに入れます。今回は、Assets/Scripts/ProtocolBufに入れます。
キャプチャ5.PNG

最後に、Unity上でProtocolManager.csを作ってください。
(サンプルコードなので、名前は任意でよいです。)
以下にサンプルコードを示します。

ProtocolManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;

using ProtoBuf;
using Moprotocol;

public class ProtocolManager : MonoBehaviour
{
    MOProtocol protocolSerialize;
    MOProtocol protocolDeSerialize;
    // Start is called before the first frame update
    void Start()
    {
        protocolSerialize = new MOProtocol();

        protocolSerialize.msgID = "999999";

        protocolSerialize.Datas.Add("テスト1", "aaaaa");
        protocolSerialize.Datas.Add("テスト2", "bbbbb");

        using (var ms = new MemoryStream())
        {
            Serializer.Serialize(ms, protocolSerialize);
            byte[] bytes = ms.ToArray();
            //シリアライズ(デバッグ用途)
            Debug.Log(BitConverter.ToString(bytes));

            //デシリアライズ(デバッグ用途)
            var ms2 = new MemoryStream(bytes);
            protocolDeSerialize = Serializer.Deserialize<MOProtocol>(ms2);
            foreach (string Value in protocolDeSerialize.Datas.Values)
            {
                Debug.Log(Value);
            }
            Debug.Log(protocolDeSerialize.msgID);
        }
    }

    // Update is called once per frame
    void Update()
    {

    }
}

上記のProtocolManager.csを任意のオブジェクトに割付け実行すると下記のログが出ます。
ログ上にシリアライズした結果、デシリアライズした結果が出てくれば成功です。

キャプチャ.PNG

おわりに

有識者ではなく、勉強中の身であるため、間違い等あれば、ご指摘等頂ければ幸いです。

なお、本ページとは話が脱線しますが、書籍のオンラインゲームを支える技術にて、バイナリデータの必要性が説明されており、導入に至りました。
この書籍は、分かりやすい上に、深い内容まで言及されているので、オンラインゲームを作るときの参考材料にもってこいです。

参考サイト

gRPCとProtocol Buffersによるアプリケーション間通信 / Unity

C#でProtocolBuffersを使う方法

Protocol Buffer Basics: C#

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2