Adsense

2008年2月27日水曜日

llDialog - Too many listens

Video 玉やダンス玉 (MLDU) などでダイアログを多用しているわけですが、以前のエントリでも書いたように一人で楽しむならあまり問題がない llDialog も、クラブのような大勢の人がタッチする環境になると問題が発生することがあります。

ダイアログから結果を受けとるチャネルの混線なども代表例ですけど、ある日突然ダイアログが表示されなくなって "Too many listens" というエラーが出るのも、大勢の人が使った結果だといえます。有効な Listen の数は 64 個までで、それを超えるとこのエラーがでます。

llListenRemove による Listen の閉じ忘れ、、、なのですが、じゃぁ、llListenRemove を入れれば必ず回避できるか、、、というとそうでもないんです。

それは timer() と複数人対応と「無視 (ignore)」の組み合わせでスクリプトのある llListenRemove が働かないことがあるからなんです。

こういう例があてはまります。

a) アバターA がタッチしてダイアログを表示
b) スクリプトは llSetTimerEvent でダイアログのタイムアウトを設定(無視・長時間放置対応)
c) アバターA がボタンを押す「前に」にアバターBがダイアログをタッチ
d) スクリプトはアバターBにダイアログを表示、「新たに」llSetTimerEvent でタイムアウトを設定
e) アバターAがボタンを押す。llListenRemove でアバターA のListen を削除
f) スクリプトはアバターAによりボタンが押されたので llSetTimerEvent を解除
g) アバターBが「無視」ボタンを押してダイアログを閉じる
h) アバターBの Listen は残り続ける

ひとつの
スクリプトで複数アバターに対するダイアログタイムアウトの処理は「ロック」をかけない限り難しいというわけですね。

「ロック」をかけるというのは、だれかがダイアログを開いているとき、違うアバターがボールをタッチしたら「現在このオブジェクトを使っている人がいるのでしばらく待ってからタッチしなおしてください。」というように1時点で1アバターしかダイアログを表示させないようにするわけです。ダイアログのボタンをおして llListenRemove が行われた、または、タイムアウトして llListenRemove が行われた、、、ということができてから、他のアバターがタッチしたらダイアログを表示する、という方法です。

これもひとつの解決方法なのですが、ちょっと悩ましくなるのが「複数ページのダイアログ」をつくった場合、その「ロック」されている時間が長くなる、、、、ということなんです。いわゆる「デッドロック」といわれるものですね。

それが「ビデオ玉」での問題だったんです。ビデオ玉は SL 内で視聴したいビデオをダイアログから選ぶ方式なのですが、ビデオが増えてダイアログのページが複数になると、ダイアログを開いている時間が長くなるので、単純なロック方式では、このデッドロックが発生しやすくなることがわかっていました。

そこで、ASUKA の雷神に新たに設置したニュービデオ玉(試験運用中)は、複数スクリプト方式に変更して、デッドロックを極力さけながら、複数アバター対応、ダイアログ複数ページ対応をしてみました。
といっても「ダンス玉」の応用なんですけどね。基本の処理の流れは以下になります。

a) DialogManager (DM) がタッチを検知
b) DM は DialogSlot(DS) に空があるかチェック
c) DS にあきがあれば、そのDSに対して llMessageLinked でアバターの Key を送信
空がなければ「しばらくお待ちください」を Touch した AV にメッセージを送信
d) DS は受け取った Key に対して llDialog および llSetTimerEvent を実施
e) 他のアバターがタッチすると DM は上記を繰り替えす
f) ボタンが押された、タイムアウトが発生したら、DS は DM に対して処理終了を通知
g) DM は処理中フラグが立っているDSを解放

DialogSlot を3つ用意してみたので、おおよそこれで対応できるかな・・・と思っています。
あと、このニュービデオ玉、llListenRemove は使わず、state change で Listen のクリアを行っています。ダイアログを表示する state と、DialogManager から message を受け取る state をわけています。ボタンがおされた、タイムアウトしたあとで state を変えることでクリアできている、ということです。
たかがダイアログ、されどダイアログ?(笑
[追記]
ガーン、スロット開放されていないし・・・
直します~(だから、試験運用は大切)