さすがにリアルタイム同期は無茶じゃないですかね…。
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の値を送れば良いと思います)