javascript内でタグを実行するときの注意事項
要約
なんか知らないけどメッセージがクリック待ちを待たずに勝手に進む!
→[iscript]~[endscript]の中でティラノスクリプトのタグ実行してない?????
説明
ティラノスクリプトを多少理解してくると、javascriptでのカスタマイズをしたくなるものです。
しかし問題なのは、[iscript]~[endscript]内でティラノスクリプトのタグを実行した場合です。このとき、タグの処理は非同期になります。
非同期 is 何
非同期とは、データを転送する際に、送信側と受信側のタイミングの一致(同期)を気にせずにデータをやり取りすることである。
――weblio辞書・IT用語辞典より引用
ここで言っている非同期とは、処理Aの実行終了を待たずに処理Bを実行するというような意味です。
実行終了までに時間のかかる処理がプログラム中にあると、実行終了を待つ時間、いわゆる処理待ちの時間が発生します。処理待ちをしている間に、処理Aとは無関係の処理Bをした方が時間を有効に使えます。時間は有限だからね
そういう場合に、処理Aを非同期の処理として、実行終了を待たずに処理Bを実行する、ということをします。
で、ティラノスクリプトではどうなるの
最初に書いたとおり、ティラノスクリプトのタグによる処理は全て非同期です。
[image]タグにwaitプロパティがありますよね。falseを指定すると画像の表示完了を待たずに次のタグに進みます。
これが非同期ということです。
非同期、しかもタグは基本的にタグの処理が終わったら次のタグ(行)に絶対に進むので、こういう書き方をすると高確率で不具合が発生します。
code:sample.ks
for(var i = 0; i < TYRANO.kag.config.numCharacterLayers; i++){
TYRANO.kag.ftag.startTag("freeimage", {
layer: i,
time: 0
})
}
前景レイヤーを全て初期化する処理です。[freeimage]タグをレイヤー数分書くのが億劫なのでこういうことをしています。
勘のいい人なら何が悪いかおわかりだと思いますが、一応解説記事なので解説します。
TYRANO.kag.ftag.startTag()はティラノスクリプトのタグを実行する関数です。この関数を使うこと自体は特に問題ありません。
問題は、タグの実行をfor文の中で行っているということです。
for文は、指定された条件の間処理を行い、その後は後続の処理を実行する処理です。
for文は同期的な処理ですが、その中のstartTag()、すなわちティラノスクリプトのタグ処理は非同期処理です。
すると何が起きるか。
さっきのスクリプトを例に説明します。
code:sample.ks
for(var i = 0; i < TYRANO.kag.config.numCharacterLayers; i++){
TYRANO.kag.ftag.startTag("freeimage", {
layer: i,
time: 0
})
}
1.for文スタート!
2.for文内のstartTag("freeimage")を実行!(1回目)
3.for文内のstartTag("freeimage")を実行!(n回目)
4.for文終わり!
5.[endscript]に到達!次のタグに進む!
6.startTag("freeimage")(1回目)の処理終わり!次のタグに進む!
7.startTag("freeimage")(n回目)の処理終わり!次のタグに進む!
あれれ~?おっかしいぞ~?
[endscript]に到達したとき、既に次のタグへ進む処理を行っているのに、その後も[freeimage]実行後の次のタグへ進む処理が実行されています。
これが、「クリック待ちを待たずに次のメッセージに進む」現象の正体です。
あれ? でも…
[endscript]タグにはstopパラメータがあるよね?
https://gyazo.com/b2d62edf6bbab09cdc17d48a6db71935
――ティラノスクリプト タグリファレンスより抜粋
リファレンスの説明のとおり、stopパラメータにtrueを指定すると[endscript]の次のタグに進まなくなります。
が、今回はfor文内でのタグ実行で、「次のタグに進む」処理が複数回実行されているため、stop=trueとしていても次のタグに進んでしまうのです。
つまりfor文の中でstartTag()は実行するなという話なんですが、そもそも[iscript]~[endscript]内でstartTag()を使うのも、javascriptの非同期処理とティラノスクリプトの処理順にについてわかってないとバグの温床になるなあと今回のバグで思いました。
みんなも[iscript]~[endscript]内でタグ実行するときは気をつけよう、なっ!(布団を敷こうおじさん)