Adsense

2008年5月21日水曜日

セカンドライフのアニメーションを操る その7

これでシリーズ最終回 (笑) でしょう。

MLDU (Massive Link Dance Unit) のベンダー販売に最後まで躊躇したものは前の投稿でちょっとご紹介した「ラグのときのノートカードの読み込み」でした。

アニメーションを操る、、、という件名との関連性が薄い話題なのですが、ノートカードによるダンス記述は MLDU では欠かせないものだったということと、llHTTPRequest といった関数を使った外部サーバー、サービスからのデータ読み込み・書き込み方法 (Sine Wave AO 1.2 方式ですね) を除けば、ユーザーさんが唯一データの追加・変更をして、スクリプト・リセットしてもそのデータを再度使うことができる、、、というものなのでご紹介させてください。

ダンス・アニメーションの再生の順番やその再生時間を MLDU ではユーザーがノートカードに記述して保管しておきます。スクリプトはノートカードを読み込み、その情報を LIST に格納して、その順番で llStartAnimation を開始し、llSetTimerEvent には該当する秒数をセットしてタイマーをかけます。
timer() イベントが発生したら、LIST の次の項目のアニメーション名と秒数を使ってアニメーションを開始し、それまで動いていたアニメーションを止める、、、この繰り返しです。

ダンス記述ノートカードは1枚ではなく複数枚利用でき、MLDU 3.2 のデフォルトは 5 つのダンスセットを準備し、リセットすることなしに即時にダンスセットを切り替えることができます。ダンス記述ノートカード1枚につき、1つのスクリプトが割り当てられています。これはより多くのメモリーを利用したいためでした。

0

それぞれのダンス制御スクリプトはノートカードの読み込み時に指定されているダンス・アニメーションが本当にあるかどうかを llGetInventoryName を使ってチェックします。llStartAnimation / llStopAnimation の時に Avatar がいない場合エラーになることをご紹介しましたが、アニメーションが無い場合も当たり前ですがエラーになります。

意外にタイプミスが多かったり、半角スペースが2つ入っているのが本当の名前、、、などがあります。エラーの場合はどのダンスアニメーションがエラーになっているかを llOwnerSay を使って表示します。ダンスアニメーションを記述する際には、アニメーションのプロパティを開いて名前の部分をマウス・ドラッグでマーキングして、Ctrl+C でコピーし、ノートカードに Ctrl+V で貼り付けるのが一番確実ですね。

ダンス制御スクリプトをシーケンシャルにリセットしたい
このダンス制御スクリプトも含めたすべてのスクリプトを制御する親スクリプトがあります。
MLDU3.2 デフォルトだと、この親スクリプトが1本、ダンス制御スクリプトが6本、ダンススロットスクリプトが 15 本の計 22 本のスクリプトが llMessageLinked を使って連携するわけですが(ちなみに雷神の MLDU はその倍の数、、)、全スクリプトのリセットは親スクリプトからの llResetOtherScript により行っていました。

実は、この llResetOtherScript は、指定したスクリプトのリセットが終わるまで処理を待つことなく、次から次へとリセットをかけることが可能なんです。というか、、、リセットしてね~、を投げっぱなし、、、、というか、、、
for 文などでまわすと、どんどんリセットがはじまります。
ここにノートカードを読み込む llGetNotecardLinedataserver イベントが非同期処理的に複数動き始めるわけですから、、、

これも、普通(何をもって普通、、、というか難しいですが、、、)はどんどんノートカードを読み込んで、アニメーションの存在チェックをしていくのですが、クラフターズカップなどが開催されてプリム数やスクリプトがSIMに多くなっている状態の雷神などはスクリプト・リセット時にノートカードが読めなくなり、エラーになることもしばしばありました。
親スクリプトによる全スクリプト・リセットを使わず、ダンス制御スクリプトをひとつひとつリセットしていくことで回避はできたのですが、これも、、、美しくないですよね、、、。
この「順番にスクリプトのリセットをかける」は、あまり難しくないように思われる方もいると思いますが、なにを悩んでいたかというと、MLDU の基本コンセプトは「スクリプトを動的に追加可能にする」だったんです。

たとえば、ダンススロットを 15 から 30 に増やしたい場合は、danceSlot というスクリプトをプリム内のコンテンツフォルダーに追加分をコピー(ドラッグ&ドロップ)するだけ、、、ダンスセットを増やしたければ、ノートカードとダンス制御スクリプトをコピーするだけ、、、というものです。

親スクリプトはいったい自分がいくつのスクリプトを管理するかは、、、決めうちじゃなく、動的にとれるようにしたかったんです。

これは、、、いろいろなやり方があるとは思いますが、最終的に私がとった方法は以下でした。

1) 親スクリプトは子のスクリプトのリセットをかける前に llGetInventoryName  と  llSubStringIndex などを使って、ダンス制御スクリプトの数を取得します。ダンス制御スクリプトは SynchManager という名前でコピーしていくと SynchManager 1,  SynchManager 2 と連番が振られますが、必ず SynchManager という文字列は含みますから、それを拾うわけですね。

2) その数ぶんだけ、親スクリプト内の slotStat という名前の List に "1" を入れます。6つあれば ["1","1","1","1","1","1"] となります。

3) 親スクリプトは llListFindList を使って "1" を slotStat から探します。

4) 一番はじめは 0 (つまり、一番最初)が戻り値としてくるので、0 の場合はなにも付け加えずに synchManager をリセットします。

5) 子スクリプトのダンス制御スクリプトはリセットが完了したら、llMessageLinked を使って、「正常に完了しました」 というメッセージと、自分の名前についている番号を投げます。番号がないときは 0 を投げます。

6) 親スクリプトは「正常に完了しました」をうけとったら、同時にもらった番号を index として使って、slotStat の中の "1" を llListReplaceList を使って "0" にします。そして、もう一度上記の 3) に戻って "1" を探します。その後は 3) ~ 6) の繰り返しです。

これで順次スクリプトリセットを可能にしてみました。途中でエラーが起こった場合はこの処理は止まります。ええ、とまっていいんです。そこは割り切りました。それでも上述のコンセプト的には80点はとれるんじゃないかなぁ、、、と、ちょっと自画自賛(笑

ちなみに、、、フリーのものも含めて、同じようなダンススクリプト、同期ダンススクリプトのソースは一度も見たことがありません。(というか、探せなかった?)
なので、上級者(プロ)の人にしてみればかなり「原始的」な処理もあると思います。ただ、半年以上のテストを比較的多くの Avatar が集まる、状況の厳しいクラブ雷神で続けてきた結果、まだまだ改善の余地はあるものの、エラーはあまり発生しない同期ダンス制御ユニットになったのかなぁ、、、と思います。
私にとっても、実践的な LSL ということで、とても勉強になりました。
クラブ雷神 : たぶん世界で一番クールなダンスを踊れます(笑
Snuript Library : MLDU 3.2 うってます。でも ネトラジ・チェンジャーが一番おすすめ(笑
[追記: 現在 MLDU は OEDO City SIM の Studio4D さんのお店にベンダーを設置しています]
このブログ「シリーズ」を書こうと思ったのは、実は、、、ダンス制御ユニットのパーソナル版を作ろうとしていて、ちょっとアイディアにつまったからでした。(笑
パーソナル版でやりたいことがこのブログを書く過程でだんだん固まってきたので、、、、お楽しみに。
でも、完成まではまだまだ先は長そうです。スクリプトって、どうしても売るの躊躇するんですよね、、、。