閉じる
閉じる
×
- 本記事はプラグイン作者や技術者向けの周知を目的としたものです。
- Chrome66でHTML5ゲームの音声が鳴らなくなる可能性のある問題と、それに対するアツマールでの対応内容を説明します。
- アツマールでは音声再生について対策は行い、殆どの場合で音声は再生できるようになります。
- 影響が少ないよう注意して対応しましたが、既存のゲーム・プラグインと競合する可能性はゼロではないため、周知する運びとなりました。
2018年4月17日の「Google Chrome66」の更新で、コンテンツの映像・音楽再生の扱いが変更になることがわかりました。
これにより、特定条件でHTML5製のゲームで映像・音楽再生がおこなわれない可能性があります。
例えば、ユーザーが初めてサイトに訪れ、クリックなどのアクションを行っていない場合が該当します。(より詳しい情報についてはリンク先を参照してください)
■RPGアツマールでの対応
この対策として、RPGアツマールでは、以下のような対応を行います。
現在、RPGアツマールではすべてのゲームにおいて、ゲーム実行前にアツマールの独自機能を実行するためのJavaScriptを実行しています。
今回はこのJavaScript中で「オーディオコンテキストをフックし、アップロードされたゲーム中で音声を再生しようとして成功しなかった場合、ユーザーがタップやクリックを行った時点で再生を行う」という対応を行いました。これにより、アツマールにアップロードされたゲームはChrome66で音声の再生が不可能な場合でも、ユーザーがクリックやタップを行った時点で音声を再生するようになります。
ただし、映像については今回の対応だけでは再生されない可能性があります。以前ご案内したプラグインを入れることで再生が可能になりますので、導入を推奨します。
今回の対応はRPGツクールMVのコアスクリプトやプラグインに配慮し、極力影響のない対応をしています。しかし、既存のプラグインとの競合など、問題が起きうる可能性はゼロではないため、プラグイン作者や技術者の皆様につきましては、留意していただけると幸いです。
以下はJavascriptに詳しい方向けの詳細な内容です。
■対応方針
1. ES6 Proxyを使ってAudioContextクラスのnew(construct)にフックを仕込む(AudioContextをProxyで包んだ物に差し替える)
2. Proxyのフックを利用して、newのタイミングで、作成されたAudioContextオブジェクトをリストに保持する
3. ユーザージェスチャタイミングでAudioContext#resume()を呼び出す
■具体的なコード(atsumaru.js)
// audio hack
var audioCtxs = [];
var hackStopped = false;
if (_window.AudioContext && _window.Proxy) {
_window.AudioContext = new _window.Proxy(_window.AudioContext, {
construct: function(target, argumentList) {
var ctx = new (Function.prototype.bind.apply(target, argumentList));
if (!hackStopped && ctx.state === "suspended") {
audioCtxs.push(ctx);
}
return ctx;
}
});
}
var clearHandler = function () {
_window.document.removeEventListener("keydown", resumeHandler);
_window.document.removeEventListener("mousedown", resumeHandler);
_window.document.removeEventListener("touchend", resumeHandler);
audioCtxs = [];
};
var resumeHandler = function() {
if (hackStopped || !_window.Promise) {
return;
}
hackStopped = true;
_window.Promise.all(audioCtxs.map(function(audioCtx) {
if (audioCtx && audioCtx.state === "suspended" && typeof audioCtx.resume === "function") {
return audioCtx.resume();
} else {
return _window.Promise.resolve();
}
})).then(clearHandler, clearHandler);
};
_window.document.addEventListener("keydown", resumeHandler);
_window.document.addEventListener("mousedown", resumeHandler);
_window.document.addEventListener("touchend", resumeHandler);
■謝辞
本情報を提供してくださったRPGツクールMVのコアスクリプトチームのくらむぼんさんに感謝いたします。