【解決】csvから配列として変数へ代入する処理をすぐに反映させる方法はないでしょうか。

返信する
アバター
サブちゃんB
記事: 27
登録日時: 2018年3月06日(火) 01:09

【解決】csvから配列として変数へ代入する処理をすぐに反映させる方法はないでしょうか。

投稿記事 by サブちゃんB »

csvファイルから二次元配列としてRPGツクールMZで用意されている変数へ代入する処理についてです。

まず、下記の処理でcsvファイルを二次元配列として読み込み、
各要素を数値型へ変換してから変数84へ代入します。

コード: 全て選択

//test_input.csv読み込み
//CSVファイルを読み込む関数getCSV()の定義
function getCSV(){
    var req = new XMLHttpRequest();
    req.open("get", "csv/test_input.csv", true); 
    req.send(null); 
	
    req.onload = function(){
	convertCSVtoArray(req.responseText); // 渡されるのは読み込んだCSVデータ
    }
}
 
// 読み込んだCSVデータを二次元配列に変換する関数convertCSVtoArray()の定義
function convertCSVtoArray(str){ // 読み込んだCSVデータが文字列として渡される
    var result = []; // 最終的な二次元配列を入れるための配列
    var tmp = str.split("\n"); // 改行を区切り文字として行を要素とした配列を生成
 
    // 各行ごとにカンマで区切った文字列を要素とした二次元配列を生成
    for(var i=0;i<tmp.length;++i){
        result[i] = tmp[i].split(',');
    }

    //項目名削除
    result.splice(0,1);

    //配列を数値型へ型変換
    for (let i = 0; i < result.length; i++) {
        for (let j = 0; j < result[0].length; j++) {
            result[i][j] = Number(result[i][j]);
        }
    }

    //最後の行がゴミになっているので除去。
    result.splice(result.length -1,1);

    //csvから読み込んだ配列を変数84へ代入。
    $gameVariables.setValue(84,result);
}
 
getCSV(); //最初に実行される
次に、ちゃんと反映されているかどうかconsole.log()で確認します。

コード: 全て選択

result = $gameVariables.value(84);

for (let i = 0; i < result.length; i++) {
    for (let j = 0; j < result[0].length; j++) {
        console.log("v84:result["+ i +"] = " +result[i]);
    }
}
以上2つの処理を1つのイベントやコモンイベントで「スクリプト」として続けて実行した場合、下記の動画のようになります。
https://youtu.be/LwxInj_vVmM

これらを別々のイベントに分けて実行した場合、下記の動画のようになります。
https://youtu.be/QGVL5cq7bV8

別々のイベントとして実行すればそれぞれ1回ずつでも問題なく変数84への代入がうまくいっていることが確認出来るのですが、
続けて実行する場合は、2回実行しないと代入が確認出来ません。
ここから察するに、イベントが終了するときになされる何らかの処理を経なければ、代入が反映されないと思われます。

上記2つの処理を2つのコモンイベントに分けて1つのイベントで実行した場合も、1つ目の動画と同じ結果になりました。
1つ目の処理をコピペして3回連続で回してから2つ目の処理を実行しても同じでした。

この代入をすぐに反映させる方法が見つからず、困っております。
$gamePlayer.refresh()や$gameMap.requestRefresh()など更新処理っぽいものは見つけたのですが、$gameVariables.Refresh()みたいなやつは見つかりませんでした。

動画撮影に使ったプロジェクトファイルは、不要そうなファイルをなるべく削ってから下記の通り共有しております。
https://drive.google.com/file/d/1cuiOKn ... share_link

変数84への代入をすぐに反映させる方法がございましたら、ご教示のほど宜しくお願い致します。
最後に編集したユーザー サブちゃんB [ 2022年12月08日(木) 23:25 ], 累計 1 回
名無し蛙
記事: 352
登録日時: 2015年11月23日(月) 02:46

Re: csvから配列として変数へ代入する処理をすぐに反映させる方法はないでしょうか。

投稿記事 by 名無し蛙 »

liuhong さんが書きました:ここから察するに、イベントが終了するときになされる何らかの処理を経なければ、代入が反映されないと思われます。
この認識は誤りです。
理由は明白でjavascriptではファイル読み込みは非同期処理だからですよ。
と、言ってもこの系統の処理は自分も疎いのであまり偉そうな事も言えないんですけど。

例えばcsvファイル読み込みに10ms程の時間が掛かると仮定すると
読み込みが完了する前に次の処理に移行するので
リクエストを出した直後に結果を参照する処理をすると未ロード状態に見えるんです。
極論リクエストを出した後に(このファイルサイズなら)ウェイト1Fでも挟めば動作すると思います。
liuhong さんが書きました:変数84への代入をすぐに反映させる方法がございましたら、ご教示のほど宜しくお願い致します。
具体的に何をしたいかにも拠りますね。
文字通りの直後ならthenで繋げれば良いでしょうけど
これを練習として本番は全く別の運用をするのならそれに合わせる必要が有るかと。

コード: 全て選択

convCSV = async() => {
    const data = await (await fetch("csv/test_input.csv")).text();
    const rows = data.split("\n");
    const result = [];
    rows.splice(1, rows.length - 2)
        .forEach(row => result.push(row.split(",").map(Number)));
    return result;
}
convCSV().then(result => {
    $gameVariables.setValue(84, result);
    result.forEach((row, i) => console.log(`v84:result[${i}] = ${row}`));
});
アバター
サブちゃんB
記事: 27
登録日時: 2018年3月06日(火) 01:09

Re: csvから配列として変数へ代入する処理をすぐに反映させる方法はないでしょうか。

投稿記事 by サブちゃんB »

名無し蛙 様、今回もご教示頂きましてありがとうございました!

読み込み時間の問題という点には全く思いが至りませんでした。
仰るとおり、2つの処理の間に1フレームのウェイトを入れるだけでうまく動作しました。

今回の質問に至った動機は、
「オープニングや長めのイベントを1まとめに実行できないと困る」
というものです。
しかし単純に読み込み時間の問題ということであれば、
最初に読み込んでおいて時間をおいてから呼び出すという対処が出来るのでこれだけで解決です。

それに加えて今回は、
async関数を使って読み込むまで処理を止めるという手法もご教示頂けて、
大変勉強になりました。

改めまして、大変有用な知見をご教示頂き感謝申し上げます。
返信する

“MZ:質問”に戻る