以前の記事で「しりとり」のアプリケーションを作成したのですが、動作が少し安定しなかったので、改善します。
前回記事のコードの問題点
今回コードを修正するaddEventメソッドを再掲します。
Cubism 4 SDK for Web R1のSamplesにあるTypeScriptのlapplive2dmanager.tsにaddEventというメソッドを追加することで、Live2Dモデルの動きを更新していました。
public addEvent(): void { const getbtn = document.getElementById("submitBtn"); getbtn.addEventListener('click', () => { setTimeout(() => { let motionNum = 0; const randRange = (min, max) => Math.floor(Math.random() * (max - min + 1) + min); let reply = document.getElementById("reply"); if (reply.textContent.indexOf('終了') != -1) { motionNum = 1; } else if (reply.textContent.indexOf('?') != -1) { motionNum = 2; } else if (reply.textContent.indexOf('次の言葉') != -1) { motionNum = randRange(3, 4); } else { motionNum = 0; } for (let i = 0; i < this._models.getSize(); i++) { this._models .at(i) .startMotion( LAppDefine.MotionGroupTapBody, motionNum, LAppDefine.PriorityNormal, this._finishedMotion ); } }, 2000); }, false); }
上記コードの場合、しりとりの単語を入力した後に「送信ボタン」が押されてから2秒後にメッセージ(CPUからの返事)の内容を確認していました。
このとき動作環境によっては、[入力した単語の表示時間(1秒) + しりとりの処理時間(形態素解析やルールの判定、次の単語の抽出等)]に1.5秒~3秒程度とバラツキがあったので、動作が不安定になっていました。具体的には次の2点のような感じです。
処理が早めに完了する場合:メッセージの表示からモーションの再生までにラグが生じてしまう
処理が2秒後に完了していない場合:メッセージの内容が確認できないため、正常なモーションの更新ができない
改良したコード
ということで、上記の問題点を改善するために、メッセージの内容を確認する回数を増やすことにしました。
public addEvent(): void { const getbtn = document.getElementById("submitBtn"); getbtn.addEventListener('click', () => { let reply = ''; const sleep = msec => new Promise(resolve => setTimeout(resolve, msec)); async function waitReply() { for (let j = 0; j < 10; j++) { await sleep(500); let getReply = document.getElementById("reply"); reply = getReply.textContent; if (/終了|?|次の言葉/.test(reply)) { return reply; } else if (j == 9) { return reply; } } } waitReply().then((reply) => { let motionNum = 0; const randRange = (min, max) => Math.floor(Math.random() * (max - min + 1) + min); if (reply.indexOf('終了') != -1) { motionNum = 1; } else if (reply.indexOf('?') != -1) { motionNum = 2; } else if (reply.indexOf('次の言葉') != -1) { motionNum = randRange(3, 4); } else { motionNum = 0; } for (let i = 0; i < this._models.getSize(); i++) { this._models .at(i) .startMotion( LAppDefine.MotionGroupTapBody, motionNum, LAppDefine.PriorityNormal, this._finishedMotion ); } }); }, false); }
async awaitを使用した連続の非同期処理は、並列に処理を実行して処理時間を短くするのが基本的な使い方ですが、今回の場合は1回1回待機時間が必要なので上記のようなコードになりました。
上記コードでは「送信ボタン」が押されてから0.5秒ごとにメッセージの内容を確認して、該当する文字が出現したらループ処理を抜け出してモーションの更新を行うようにしています。
そのため、しりとりの処理時間に影響されることなく、安定してモーションの更新ができるようになりました。
しりとりアプリの動作
アプリケーションの動作自体に変更点はないので、以前の記事で動作確認した時の映像を載せておきます。