RPGツクールMVに於いてゲームを作るにあたり、私が最もよく見かけるプラグイン導入時のエラーが、この
「Cannot read property ○○ of undefined」
です。
(○○には任意の変数名や関数名が入ります)
#このエラーは一体…!?
直訳すると、
「アクセスしようとしてる変数が初期化されてねーから、その中に○○って変数/関数はねーよ」
となります。
例を見てみましょう。
Game_Action.prototype.itemHit = function(target) {
if (this.isPhysical()) {
return this.item().successRate * 0.01 * this.subject().hit;
} else {
return this.item().successRate * 0.01;
}
};
↑これを…
こうじゃ↓
Game_Action.prototype.itemHit = function(target) {
var x = this.unknownVar.hit; // ←!?!?
if (this.isPhysical()) {
return this.item().successRate * 0.01 * this.subject().hit;
} else {
return this.item().successRate * 0.01;
}
};
(今回は実験用にこうしているだけであって、プラグインを使わずに直接rpg_objectを変更するのはトラブルにつながるので良い子はまねしないでね!!)
で す よ ね ーーーーーー
#れっつ・デバッグ(原因探し)
バグが出ている場合、何はともあれ、先ずはデバッグ画面を見るのが先決です。
なになに……
デバッグ画面に於ける一連のfunctionの列挙は、上に行くほど直接的な原因となったコマンドに「近い」物となります。
この場合rpg_object.js の Game_Action.prototype.itemHitの中で発生している、と言う事ですね。
「Cannot read property 'hit' of undefined」
まさか…hitがundefinedなのか!?
いいえ違います
先ほどの言葉をもう一度見ましょう。
「アクセスしようとしてる変数が初期化されてねーから、その中に○○って変数/関数はねーよ」
――つまり、この場合undefinedなのは、this.unknownVar
なのです。
試しにconsole.log
で出力してみましょう。
Game_Action.prototype.itemHit = function(target) {
console.log(this.unknownVar);
var x = this.unknownVar.hit; // ←!?!?
if (this.isPhysical()) {
return this.item().successRate * 0.01 * this.subject().hit;
} else {
return this.item().successRate * 0.01;
}
};
まぁundefined
でしたねー。宣言していないんで当然の話なのですが。
#終わりに
今回の例では簡略化のため宣言されていない変数を使ったので、調査はここでおしまいなのですが…
若しも問題がプラグイン同士の競合に由来する場合、更にそのundefinedとなっていた変数をコード内で検索し、どこで値が入れられていたのか。何故その値を入れるはずだったコードが実行されていないのか
(私が見たことがあるのは、同じfunctionをOverrideしていたがために片方の存在が抹消されていたパターンやら、そもそもオブジェクトごと闇に葬り去られて使われなかったパターン、新規に作ったオブジェクトで、initializeの際に必要手順を怠ったパターンなど)
具体的な調査が必要となります。
ここら辺は経験やら理解が物を言う部分になって来ます。
この文が悩む皆様の役に少しでも役に立てば、と思います。
と言うか調査する際最低限デバッグ画面から個人情報を消した物を提供していただけると大分やりやすくなります…
もっと広まれ!デバッグ画面添付!