laravelのクエリビルダで取得したデータを圧縮してUnity側で解凍する方法

2023年8月15日火曜日

laravel Unity vue.js

t f B! P L

 laravelのクエリビルダで取得したデータを圧縮してUnity側で解凍する方法







データベースから取得した大量のデータをUnityのWebGLへ渡してシミュレーション結果を3Dで表示するWebアプリを作ってみました。

その際に困ったのが次の2点です。

・サーバからのデータのダウンロードに時間がかかりタイムアウトする
・Unity側にデータを送るときにエラーが出る


Unity側のエラーは、「Out of memory. if you are …」というもの。
メモリサイズの設定を変えれば回避できるようですが、そもそもデータ量をもっとコンパクトに出来ないかと思い、データを圧縮して受け渡すことにしました。

その時の「圧縮」と「解凍」部分のプログラムです。



laravel(PHP)側のプログラミング


サーバ側はlaravelを使っています。
クエリビルダを使ってクエリ文を作ってDBからデータを取得しています。
DBはmySQLで作りました。


laravel

// クエリビルダを使ってDBからデータを取得する

$db_data = DB::table('simulation_data')

    ->select('create_at', 'data1', 'data2', 'data3', 'data4', 'data5')

    ->where('vibrated_at', '<=', $nowDate)

    ->get();


// データを圧縮する

$str_data = json_encode($db_data->toArray());  // 配列にしてJSONに変換

$gz_data = gzencode($str_data, 9);   // gzip圧縮

$gz_base64 = base64_encode($gz_data);  // BASE64エンコード

$simulation_data['gz_base64'] = $gz_base64;

$simulation_dataを返信する


gzip圧縮したデータはバイナリなのでそのままだと返信データに使用できません。
なので、BASE64エンコードで文字列にします。
文字列にすると圧縮率が下がりますが、思ったよりデータは小さくなりますよ。




Javascript(vue.js)側のプログラミング



Javascriptにはvue.jsを使ってみました。
サーバとUnity WebGLの間でデータを受け渡しするだけです。


Javascript

// 通信処理

axios({

    url: '/api/simulation/get_data/',  // アクセスURL

    method: 'POST',

    params: {}

}).then(response => {

    if (response.status !== OK) {

        alert("通信エラー:" + response.status);

    }


    // UnityLoader.instantiate()で生成したUnityインスタンス

    unityInstance.SendMessage(

        'Canvas',
        'SetSimulation',  // 関数名

        JSON.stringify({

            "simulation_data": response.simulation_data// そのまま渡すだけ

        })

    );

});






Unity WebGL(C#)側のプログラミング


JSONをシリアライズするのにMiniJSONを使っています。
UnityのスクリプトはC#を使っています。


Unity(C#)

using MiniJSON;

using System.IO;

using System.IO.Compression;


// データを処理する関数

public void SetSimulation(string simulation_data)

{

    Dictionary <string, object> data_list = Json.Deserialize(simulation_data) as Dictionary<string, object>;


    string gz_base64 = data_list["gz_base64"];

    byte[] gzData = Convert.FromBase64String(gz_base64);  // base64からgzipへ

    string jsonData = DeComporessGZIP(gzData);  // gzipからJSONへ


    var unzip_data = MiniJSON.Json.Deserialize(jsonData) as IList;

    foreach(Dictionary <string, object> data in unzip_data)

    {

        Debug.Log(data["create_at"]);  // 解凍されたデータ

    }

}


// gzipからJSONへ変換する関数

public static string DeComporessGZIP(byte[] _bytes)

{

    using(var memoryStream = new MemoryStream(_bytes))

    {

        using(var deflateStream = new GZipStream(memoryStream, CompressionMode.Decompress))

        {

            using(var reader = new StreamReader(deflateStream))

            {

                    return reader.ReadToEnd();

            }

        }

    }

}




昔からよくある圧縮方法ですが、簡単に実装できるので是非試してみてください。
以上です。



このブログを検索

ブログをよくする

自己紹介

自分の写真
はじめまして。はるはるです。 中2の息子と小5の娘を抱える2児の父です。今はゲーム会社で働いています。 子供のプログラミング学習に協力できるように教え方を勉強中です。 このブログでは簡単なゲームを作りながら自分が学んだことを少しずつ共有していきます。 情報処理の試験をたまに受けます。 第二種情報処理技術者 ソフトウェア開発技術者 基本情報処理技術者 応用情報処理技術者 twitter: https://twitter.com/amaruchan007

連絡フォーム

名前

メール *

メッセージ *

QooQ