Appendix

広告

Entries

プラグイン更新と競合問題

下記のプラグインを更新しました。

不具合修正
アニメーション画像先読み
他多数

[不具合修正]は新たに見つかった不具合と、入れ忘れてた不具合を追加しました。

[アニメーション画像先読み]は先週の日記に書いた通り、バージョン1.5への対応です。

他多数 と省略されてるものは、後で書く競合問題への対処です。



そういえば先週、バージョン1.5で追加された
「イベント実行時にイベント中に使う画像ファイルを先読み込みする」機能について書きました。

これってよく考えたらちょっとした問題がありますね。

もしも「条件によって表示されるアニメーションまたはピクチャが変わる」ようなイベントを作った場合、
イベント中にあるアニメーション画像またはピクチャ画像を上から順にすべて読み込んでしまいます。

極端に表示が遅くなるようなことはありませんが、
メモリの圧迫や後に使う画像やSE等の読み込み速度低下につながります。

これの回避策はスクリプトを使った直接指定しかないです。

コモンイベントを使っても、コモンイベント先で使う画像も読み込むため、回避策にはなりません。

せめて公式プラグインによる任意で実装にすべきだったんじゃないかなーと思います。



今週スクリプトを作っていて、ふとある競合が発生しました。

私もJavaScriptはMVから触り始めた人間なので、こんな競合が起こるとは思ってもみませんでした。

スクリプトの競合についてのお話なので、スクリプト組んでない方には関係ないお話です。


さて、下記のような二つのプラグインがあったとしましょう。

プラグインA
var _Window_Base_update = Window_Base.prototype.update;
Window_Base.prototype.update = function() {
    _Window_Base_update.call(this);
    this._a++;
};

プラグインB
var _Window_Help_update = Window_Help.prototype.update;
Window_Help.prototype.update = function() {
    _Window_Help_update.call(this);
    this._b++;
};

変数 this._athis._b は初期化してあるものとします。

ほぼ同じような内容ですが、
プラグインAは問題ないのですがプラグインBは競合が起こる可能性のあるプラグインだったりします。

普段プラグインを作っている方々、プラグインBのダメなところがわかるでしょうか?




では実際動作させた場合どうなるか試してみましょう。

プラグインAを導入した場合、
ウィンドウの update が呼び出されるたびに this._a が+1されます。
問題ありません。

プラグインBを導入した場合、
ヘルプの update が呼び出されるたびに this._b が+1されます。
問題ありません。

プラグインAプラグインBを導入した場合、
ヘルプの update が呼び出されるたびに this._athis._b が+1されます。
問題ありません。


では何が問題なのか?

実はプラグインBの後にプラグインAを導入した場合、
ヘルプの update が呼び出されるたびに this._b だけが+1されます。
逆にすると競合が起こるのです。


なぜこんなことが起こるのか?

簡単にまとめるなら、ツクール側のスクリプトに Window_Help.prototype.update が無いからです。


なぜそれがないと競合が起こるのか?

その原因はプラグインBの1行目にあります。

1行目では Window_Help.prototype.update を別の変数に入れてます。

ですが、 Window_Help.prototype.update はないので何が入れられるかというと、
上位クラスである Window_Baseupdate が変数に入れられます。

ここで呼び出される Window_Baseupdate
プラグインAによって再定義される前の update です。

そうなると、プラグインB_Window_Help_update.call(this) では
プラグインAで再定義される前のものが常に呼び出されることになります。

なので this._a が+1されないわけです。



Rubyでは起こらない競合なので、こんなことが起こりうるとは思ってもみませんでした。

逆にしないと起こらないため、知らないうちに自分が作っているプラグイン同士で競合が起こる
なんてこともあるわけです。


公式が配布しているプラグインではどう対処しているのだろうと思って調べてみたら、
そちらの作者の方々も対処しておらず、プラグインBのような書き方をしてました。

この調子ではほとんどのプラグイン作者が対処していないことでしょう。



ではどのようにスクリプトを組めばいいのか?

普通に上位クラスの update を呼び出すだけでは、
別のプラグインで Window_Help.prototype.update を再定義していた場合、
そのプラグインと競合が起きてしまいます。

そのどちらにも対応するためには、おそらく下記のようにするのが良いかと思われます。

プラグインB
var _Window_Help_update = null;
if (Window_Help.prototype.hasOwnProperty('update')) {
    _Window_Help_update = Window_Help.prototype.update;
}
Window_Help.prototype.update = function() {
    if (_Window_Help_update) {
        _Window_Help_update.call(this);
    } else {
        Window_Base.prototype.update.call(this);
    }
    this._b++;
};

Window_Help.prototype.hasOwnProperty('update')
Window_Help クラスに update があるかどうかを調べられます。

ある場合は別プラグインで書き換えられた Window_Help.prototype.update を入れて呼び出す、
なければ上位クラスの Window_Base.prototype.update を呼び出す、
これで両方に対応できます。



正直、これはMVプラグイン作者にはもっと知られてないとまずいレベルだと思います。

というわけで、心当たりのある方はすぐに対処を!

スポンサーサイト
この記事にトラックバックする(FC2ブログユーザー)
http://woodpenguin.blog.fc2.com/tb.php/265-74b93da0

トラックバック

コメント

コメントの投稿

コメントの投稿
管理者にだけ表示を許可する

Appendix

プロフィール

木星ペンギン

Author:木星ペンギン
ほぼツクールのことばかり書いてます。
名前は↑から取りました。
木製ですが木星です。
トカゲは関係ありません。

ゲーム

  • 箱庭の勇者たち(体験版)
  • アクイ ト アイ
  • ぼくらの大革命!
  • 勇者がやらねば俺がやる!
  • 3Turn Battle!
  • 3TurnBattle!2nd 体験版

メールフォーム

wood_penguin@yahoo.co.jp

名前:
メール:
件名:
本文: