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();

            }

        }

    }

}




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



ラベル

3DCG AdSense AI Amazon Echo Blender Blogger cron Cursor DNS Fire TV GCP Github Copilot Google Cloud HTTP iOS IPA iPad iPhone5 JavaScript laravel mySQL nodejs PhotoShop PHP Python Redis Scratch SSH Unity vue.js Webサーバ Windows10 WinSCP イヤーカフ型 イラスト おかし おやつ オリンピック お文具 カイワレ大根 ガチャ きのこ ギフト キャラ弁 クリスマス クレジットカード ゲーミング ゲーミングキーボード ゲーミングマウス ゲーミングマウスパッド ゲーミングモニター ゲームパッド ゴーヤー栽培 コナン サーバ サイクリング サイバーセキュリティ サイバー攻撃 サブスクリプション しりとり すイエんサー スクラッチ スマートウォッチ スライム セキュリティ ゼロトラスト ダイエット タブレット ドズル社 なわとび バーテープ パズル パンダ ぷよぷよ ふるさと納税 プログラミング プロトコル番号 マイクラ マイクロソフト マリオ マンガ メモ ランニングウォッチ ランニングゲーム ワイヤレスイヤホン 異世界 絵本 株関連 鬼滅の刃 健康診断 工作 磁石 自転車 自動化 収益化 書き初め 小学校 松屋 情報処理 情報処理安全確保支援士 辛辛魚 水泳 生成AI 折り紙 川渡し問題 銭天堂 誕生日 段ボール 知育菓子 中学受験 冬鳥 動画 動画編集 日常 認定試験 粘土 福袋 便利な雑貨 母の日 銘酒 料理

このブログを検索

ブログをよくする

連絡フォーム

名前

メール *

メッセージ *

QooQ