0 支持
(180 ポイント)
Vector3[300000]

Color32[300000]

上記2つの配列データをOnMonobitSerializeViewで送受信すると処理がとても重くなってしまい、まともに動作しませんいい方法はありますでしょうか?

送受信のやり取りは1対1で行います。

回答 2

0 支持
(230 ポイント)
編集
vector3って、4バイトx3=12バイトですよね?

単純計算でそれを300000個もおくったら約3.4MBになるので

1秒間隔で送ったとしても27.2Mbps以上の帯域が必須になりますね。

Color32も4バイトなので1.14MB→9.12Mbpsとしたら

27.2Mbps+9.12Mbps=36.32Mbpsですね…。

同期頻度によりますが、データ量が多すぎるような気がします。

余計なお世話かもしれませんが、作ろうとしているコンテンツが

Wifiや4Gなどの無線コンテンツなら、通信機器がボトルネックになる可能性があるので

データを削減する方向に動いたほうが良いかもです…
(230 ポイント)
編集
ちとモノビットエンジンのドキュメントを見てみたのですが、
特段圧縮オプションもなさそうですね…。
自前で通信を圧縮するか、データを削減するかの2択なような気がします。
(180 ポイント)
お返事ありがとうございます。
自前で通信を圧縮する方針でいこうと思います、データを圧縮してMonobitで通信するにはどのようにすればよいのでしょうか?
(230 ポイント)
まだよくわかってないのですが、下にrcvさんが書いた方法をやってみるのもいいと思います。
気になるのは同期頻度ですね。
秒間何回送るかによって、下の案でいけるかどうかも変わってきそうなので。
0 支持
(1.6k ポイント)
編集

さすがにリアルタイム同期は無茶じゃないですかね…。
C#(.NET4.5)で広く一般的に使われていると思われるDeflate圧縮を使って送信したとしても圧縮率はせいぜい50%~75%くらいだと思いますし、

無圧縮:12byte*300000+4byte*300000=約4.8MByte
Deflate圧縮(ほぼ最大効率):4.8MByte*0.25=約1.2MByte

更にこれを MonobitNetwork.updateStreamRate の値に従って、例えば初期値(=10)のままであれば、1秒間に10回送信することになるので、

無圧縮:4.8MByte*10=48MByte/s=384Mbps
Deflate圧縮(ほぼ最大効率):1.2MByte*10=12MByte/s=96Mbps

です。当然これ1つ以外にもMUNのアプリケーションが、更に言えばあらゆるネットワーク接続媒体が1回線に集中するわけですから「メチャクチャ安定した時間帯での10G対応光接続回線」くらいでもなかなか難しい気がします。

とは言っても打開策がないわけではありません。ある程度分散して「よりリアルタイムに近い同期」を行えるようにすれば良いかと思います。

1. 300000個を1度に送り付けるのではなく、3000個ずつに分けて送る(すべての情報を送りつけるまで100回同じメソッドを実行するようにする)。
2. 送信するデータについて事前に圧縮、受信したデータについて事後に解凍する。

この辺を意識すると、こんな感じで組み込めるかと思います。

        Vector3[] vectors = new Vector3[300000];
        Color32[] colors = new Color32[300000];

        int offset = 0; // 送信側で管理する、vectors, colorsのオフセット値


        // オブジェクトの同期データについて独自情報を読み書きします。
        public void OnMonobitSerializeView(MonobitEngine.MonobitStream stream, MonobitEngine.MonobitMessageInfo info)
        {
            if (stream.isWriting)
            {
                // 送信側で「オフセット値+3000」まで送信する時のbyteArrayを作成する
                Byte[] bytes = BitConverter.GetBytes(offset);
                for (int index = offset; index < offset + 3000; ++index)
                {
                    //vectors
                    bytes = bytes.Concat(BitConverter.GetBytes(vectors[index].x)).ToArray();
                    bytes = bytes.Concat(BitConverter.GetBytes(vectors[index].y)).ToArray();
                    bytes = bytes.Concat(BitConverter.GetBytes(vectors[index].z)).ToArray();
                    //colors
                    bytes = bytes.Concat(new byte[] { colors[index].r }).ToArray();
                    bytes = bytes.Concat(new byte[] { colors[index].g }).ToArray();
                    bytes = bytes.Concat(new byte[] { colors[index].b }).ToArray();
                    bytes = bytes.Concat(new byte[] { colors[index].a }).ToArray();
                }
                // 送信側のオフセット値を3000進める
                offset = (offset + 3000 >= 300000)? 0: offset + 3000;

                //得られたbyteArrayをDeflate圧縮する
                MemoryStream compressed = new MemoryStream();
                DeflateStream deflateStream = new DeflateStream(compressed, CompressionMode.Compress);
                deflateStream.Write(bytes, 0, bytes.Length);

                // 圧縮したデータを送信
                stream.Enqueue(compressed.ToArray());
            }
            else
            {
                // 圧縮されたデータを解凍しbyteArrayを得る
                MemoryStream compressed = new MemoryStream(stream.Dequeue() as Byte[]);
                DeflateStream deflateStream = new DeflateStream(compressed, CompressionMode.Decompress);
                MemoryStream decompressed = new MemoryStream();
                deflateStream.CopyTo(decompressed);
                Byte[] bytes = decompressed.ToArray();

                // 送信側で設定したオフセット値の取得
                int _startIndex = 0;
                int _offset = BitConverter.ToInt32(bytes, _startIndex);
                _startIndex += 4;
                // 送信側で「オフセット値+3000」まで送信された情報を1つずつ取得する
                for (int index = _offset; index < _offset + 3000; ++index)
                {
                    //vectors
                    vectors[index].x = BitConverter.ToSingle(bytes, _startIndex);
                    _startIndex += 4;
                    vectors[index].y = BitConverter.ToSingle(bytes, _startIndex);
                    _startIndex += 4;
                    vectors[index].z = BitConverter.ToSingle(bytes, _startIndex);
                    _startIndex += 4;
                    //colors
                    colors[index].r = bytes[_startIndex]; ++_startIndex;
                    colors[index].g = bytes[_startIndex]; ++_startIndex;
                    colors[index].b = bytes[_startIndex]; ++_startIndex;
                    colors[index].a = bytes[_startIndex]; ++_startIndex;
                }
            }
        }
 

動作未検証ですが、こんな形であれば「すべてのVector3 & Color32 が同期するまで100回(MonobitNetwork.updateStreamRateが10であれば10秒)あれば全ての情報が同期されます。もっとも10秒分だけのラグが許容できればですが。

この上でさらに同期データ本体が1/100されることになるので、

無圧縮:384Mbps/100=3.84Mbps
Deflate圧縮(ほぼ最大効率):96Mbps/100=960Kbps

まで負荷を軽減できます。

もっともこれでも高いレベルだとは思いますので、やはり300000個の配列を送る処理自体を見直すべきかと思います(例えばそれらの情報が1つの乱数seedで調整できるような内容であれば、それこそその乱数seedの値を送れば良いと思います)

...