2009年7月4日土曜日

ドアのスクリプトをいじくり倒す

む、Hidenoriさん、さすが、問題点をまとめて下さった

stateの分け方、使い所
寡聞にしてこのstateというもの、セカンドライフに来てはじめて知った制御構造なので、まだ、それほど経験がないため、細かい実装に関してはよく分からない部分があります。そこで一般論としての話になってしまいますが、みどりさんが書いているブログのこのあたりに一般論としての正解があるように思います。
原則的に、ステートチャート図を書いたときに遷移条件が、外的条件によって複数に分かれるもの(私は停留があると表現してます)はLSLでもステートになるでしょう。
問題は、ただ単に通過するステートの存在を許すか、許さないかになると思いますが、そのステートの中でのみ使われるイベントハンドラがある場合(例えば、初期化時にノートカードの読み込みを行うなど)は、十分にステートの候補になります。
また、逆に複数の契機によって同じイベントが発生する場合(例えば、dataserver(key queryid, string data)イベントは、ノートカードの読み込みだけではなく、他の関数の実行でも、イベントが発生します)も、ステートに分けてしまうことができるならば、分けてしまった方が良いと思います。
LSLはイベント・ドリブンな環境なのですから、そこに注目というか、それをよりどころにすれば良いと思います。
また、これは、実装者の個性が出る部分でもあります。

関数にどこまで入れるのか
ソフトウエア工学的には、モジュールの結合度は低く抑えるのが再利用という観点から見たときにはよろしい、ということになっています。私がソフトウエアタイマーの起動処理(llSetTimerEvent)を関数の外に出したのは、まさにモジュールの結合度を低めるためです。仮にこの関数を他のところで使い回す必要が出たときに、関数内部でソフトウエアタイマーを起動しているとすると、この関数を使うことができるステートには、必ずtimerイベントのハンドラがなきゃいけない(ここは突っ込みどころで、必ずしもtimerイベントがなくても動作すると思います)と言うことになれば、使い勝手が悪い。いや、経験がないので、悪そうだと考えたからなのです。
また、ドアを開けることと、時間がたてば自動的にドアを閉めることが、不可分の関係にあるならば、ドアを開ける関数内でソフトウエア・タイマーを起動しても良いでしょう。しかし、開けっ放しにしておく(おきたい)ドアもある得るということが、頭の片隅をよぎったため、分離するということの補強材料になりました。
かてて加えて、イベント・ドリブン型のプログラミング言語で、ソースコードの可読性を考えた場合、契機となるllSetTimerEvent関数の呼び出しと、その処理を行うtimerイベントハンドラが、近くにあることでよりわかりやすくなると信じてもいます。

初期rotationをいつ保存するか
これは、初期rotationを保存する目的に関わる問題です。初期rotationを保存する目的は、ドアが閉じているときに、ドアを開けた後、ドアを元に戻すために保存しているのですから、ドアを開ける直前の、ドアが閉じた状態を保存すべきです。これは自明のことで議論を待たないと思いますが、それがいつであるのかという部分は、LSLに対する知見の有無というか、誤解があると実装を失敗するように思います。

以上は、私がLSLに関する知識があまりないまま、一般論として書いた物ですので、LSLに詳しい方から、特にタイミング関連については、かなり突っ込みがあると思います。そのあたりのことの、フォローお願いします。

0 件のコメント:

コメントを投稿