BlackSheep-LSL@Wiki rez!
※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。


はじめに


初級者向けに説明すべきことはもはやほとんど残っていません(^^;
もちろん、lslに関してはまだまだ膨大な機能があり、触れていない部分は多いのですが、あくまでも「初級」ということであれば、残っているのは今回扱うrezを含めて2、3の項目くらいかと思います。

ちなみに今まで一切触れてこなかった機能として、物理系のスクリプトがあります。
物理系のスクリプトとは、SL内の物理的なオブジェクトを扱うための関数群のことです。
例えば加速させたり、重力を無くしたり、コマのように回転する力を加えたりできるのですが、これらの関数についてはスクリプトの知識というよりはSL内物理学の知識が必要になってきますので、初級者向けの対象外としました。
ちなみに、乗り物(ビークル)を作成する際には物理系スクリプトが必須です。
そのうち「乗り物を作ろう」の回があるかもと期待してた方、ごめんなさい(^^;
初級者さん向けとしてはちょっと難しいかもしれません。

また、HTTPを使った外部Webサービスとのやり取りに関しても言及していません。
lslの範疇を越え、Webサービスの構築についても説明しないとわかりにくいでしょうし、そうなると初級者の方には無用な混乱を引き起こしかねないからです。

残っているlslの機能の中で、説明しておくべきかもしれないと思っているのは、rez、衝突判定、サーチ、アタッチの4つです。
今回はその中のrezについて説明したいと思います。

rezする


オブジェクトをワールド内に出現させることをrezと言います。
rezとはresolvedの略です。
と言っても、コレ専門用語なんで、普通の英語としては通じません。

遥か昔、遠い銀河の彼方で、TRONという映画がありました。
確か史上初のコンピューターグラフィックムービーだったと思いますが、その映画の世界で使われていた用語です。
バーチャルリアリティの分野で一般的に使われているのかどうかは知りませんが、SLは多分意図的にTRONの用語を継承しているのでしょう。

rezは誰でも普通に行っています。
インベントリからオブジェクトをワールドにドロップするのがrezです。
また、スクリプトで制御してrezを行うことも可能です。

スクリプトからオブジェクトをrezするには、llRezObject()関数を使います。

llRezObject


llRezObject(string inventory, vector pos,
            vector vel, rotation rot, integer param);

順番に引数を見ていきましょう。

  • string inventory

rezするオブジェクトの名前です。
コンテンツの中に入っているオブジェクトでなければいけません。

  • vector pos

rezする位置です。
絶対座標での指定になります。
ただし、rezを実行するオブジェクト(呼び出し元)の位置から10m以内でなければいけません。
遥か彼方にrezしようとしてもエラーにはなりませんが、何も起きません(いっそエラーにしてくれたほうがわかりやすいのですが(^^;)。

呼び出し元オブジェクトからの相対位置にしたい場合は、
 llGetPos() + <4.0, 4.0, 0.0>
のようにします。
この例だと呼び出し元のオブジェクトからX方向に4m、Y方向に4mの位置にrezされます。

  • vector vel

rezしたときにオブジェクトに加える力です。
弾丸などを作る場合にはここに弾の射出速度を指定します。
ただし、このパラメータは物理オブジェクトにしか効果がありません。
今回は物理オブジェクトを扱いませんので、このパラメータにはZERO_VECTORを指定します。

  • rotation rot

rezしたときのオブジェクトの回転角度です。
椅子を作ったときのオマジナイで指定するのがわかりやすいでしょう。

  • integer param

自由に設定できる数値パラメータです。
呼び出されたオブジェクトにスクリプトがあれば、ここで指定した数値を受け取ることができます。
これについては後述します。

具体的な例を挙げておきましょう。
例えば、"Kappamaki"という名前のオブジェクトを、呼び出し元のオブジェクトの1m上方に、回転させずにrezしたい場合は、

 llRezObject("Kappamaki", llGetPos() + <0.0, 0.0, 1.0>,
             ZERO_VECTOR, ZERO_ROTATION, 1);

このようになります。
引数の数は多めですが、それほど難しくはないかと思います。

rezされる


と、呼び出し元のほうで使うllRezObject()関数について説明しましたが、一方、呼び出されたほうのオブジェクトはどうなっているのでしょうか。
呼び出されたほうのオブジェクトでは、rezされたときにイベントが発生します。
このイベントをon_rezイベントと言います。

on_rez?(integer param)


 on_rez(integer param){
   // rezされたときの処理
 }

引数paramは、llRezObject()関数の最後の引数を受け取ります。
先ほどの河童巻きrezの例で言うと、

 llRezObject("Kappamaki",llGetPos() + <0.0, 0.0, 1.0>,
             ZERO_VECTOR, ZERO_ROTATION, 1);

最後の引数には1が指定されているので、on_rez?イベントの引数には1が入ってきます。

ちなみにこのon_rez?イベント、インベントリからオブジェクトをドロップしたときにも発生してくれます。
その際には引数は常に0です。

しばしば見かける使い方ですが、

 on_rez(integer param){
   llResetScript();
 }

これはオブジェクトがrezされるたびにスクリプトをリセットしたいときの書き方です。
通常、オブジェクトの中に仕込まれたスクリプトは、オブジェクトがインベントリに収納された時点で動作を停止し、rezされると停止した状態から引き続き動き出します。
ですが時として、rezするたびにスクリプトを最初から実行したい場合があり、そんなときには上記のようにon_rezイベントの中でllResetScript()関数を実行します。
llResetScript()はスクリプトをリセットする関数です。

temp rezスクリプト


さてさて。
llRezObject()関数を使って、有用なスクリプトを一つ作ってみましょう。
一般にtemp rezと呼ばれる仕組みです。

SLでは土地の上に置けるprim数に制限があり、狭い土地では置きたいものも思うように置けないと悩んでいる方もいらっしゃるかと思います。
temp rezを使うと、擬似的にprim数の上限を増やすことが可能です。
あくまでも擬似的に、です。裏技的な手法ですので、いかなる場合にも有効なわけではありません。

temp rezは一時的なオブジェクトを一定時間ごとにrezし、あたかもそのオブジェクトがその場所にずっと置かれているかのように見せかけるスクリプトです。
ご存知かもしれませんが、一時的オブジェクトは1分ほどで自動的に消滅します。
ですがスクリプトを利用して1分ごとに同じ位置に一時的オブジェクトをrezすると、見た目はずっと存在しつづけているように見えるのです。
一時的オブジェクトは、土地のprimの限界数を越えてrezすることができるので(無限ではありません。一時的オブジェクトの数にも限界があります)、prim数の少ない土地でも置き物などを配置することが可能になります。

一時的オブジェクトの作り方をご存知ない方のために簡単に説明しておきましょう。、
buildツールの「オブジェクト」タブで「一時的」の項目にチェックを入れると、そのオブジェクトは一時的なオブジェクトになります。
チェックを入れたらすぐにtakeか「コピーをとる」でインベントリに保存してください。
さもないと1分後にオブジェクトが消滅します(^^;

temp rezを行うには、まず配置したいオブジェクト(置き物や家具など)を「一時的」なオブジェクトに変更します。
オブジェクトをインベントリに確保しておき、新たに「呼び出し元」となるprimを一つ作ってください。
「呼び出し元」はどんなprimでも構いませんが、見栄えをよくするためには透明テクスチャなどで見えなくしておくと良いかと思います。
「一時的」にしたオブジェクトを、「呼び出し元」のコンテンツの中に入れます。

そして以下のスクリプトを「呼び出し元」のprimに組み込みます。

default{
  state_entry(){
    llSetTimerEvent(60.0);
  }

  timer(){
    llSetTimerEvent(0.0);
    llRezObject("Kappamaki", llGetPos() + <0.0, 0.0, 0.0>,
      ZERO_VECTOR, llGetRot(), 0);
  }

  object_rez(key id){
    llSetTimerEvent(60.0);
  }
}

やってることはごく単純です。
60秒ごとに"Kappamaki"という名前のオブジェクトを、自分と同じ位置・同じ角度(呼び出し元と同じ位置・同じ角度)で出現させているだけです。
"Kappamaki"の部分は皆さんの一時的オブジェクトの名前に合わせて書き換えて下さいね。

object_rez?イベントについては説明してませんでした。
このイベントは、「オブジェクトをrezできたとき」に発生するイベントです。
on_rez?イベントと混同しがちですが、on_rez?イベントが「呼び出し先」で発生するのに対し、object_rez?イベントは「呼び出し元」のスクリプトで発生します。

ここではobject_rez?イベントを受け取った時点でタイマーを発動しています。
すなわち、「オブジェクトをrezできたとき」から60秒後に再びllRezObject()関数が動くようにしているのです。
rezはどうしてもラグの影響で遅れることが多く、前のrezが完了していないのに次々にオブジェクトをrezする事態を避けるためにこのようにしています。

うまく「一時的」オブジェクトがrezされることを確認したら、あとはbuildツールと使ってこの「呼び出し元」のオブジェクトの位置と角度を調整し、正しい位置と角度で「一時的」オブジェクトがrezされるようにすればOKです。

なお、temp rezには欠点もあります。
出現させるオブジェクトが「一時的」である以上、そこに座ったり、「一時的」オブジェクトの中でスクリプトを動かしたりするのに無理があります。
見かけ上は同じオブジェクトが存在しているように見えても、実際には違うオブジェクトに次々に摩り替わっているということをお忘れなく。

また、ひたすらにtimerを回し続けてllRezObject()を頻繁に使うのは負荷の原因と成り得ます。
多数のprimでできている「一時的」オブジェクトを呼び出したり、temp rezをいくつも設置したりすれば、それだけサーバーには負担になるのは間違いありません。
使用の際には十分に負荷に注意し、もしもラグが激しくなったと感じるようなら撤去して様子を見たりすべきでしょう。

さらに初歩的なミスですが、くれぐれもrezされるオブジェクトを「一時的」にし忘れないようにしてください(^^;
「一時的」にしておかないと、出現したオブジェクトはいつまで経っても消えません。
にも関わらず、1分ごとに新たなオブジェクトがrezされてきますので、土地のprim数は一気に食いつぶされ、何も置けない状態になります。
前に私はこの初歩的ミスをやらかし、土地に無数の鉄人28号を出現させたことがありますw

言うまでもありませんが、人の土地や公共の場で、許可も得ずに大量のオブジェクトをrezするのはスパム行為とみなされます。
テストの際はきちんと土地のオーナーに許可を取っておくか、あるいは自分の土地など、迷惑のかからないところで試したほうが無難です。

今回のポイント


  • オブジェクトをrezする:

 llRezObject(string inventory, vector pos,
             vector vel, rotation rot, integer param);

  • rezされたときのイベント:

 on_rez(integer param){
   // rezされたときの処理
 }

  • スクリプトのリセット:

 llResetScript();

  • オブジェクトがrezできあたときのイベント:

 object_rez(key id){
   // rezできたときの処理
   // 引数idはrezできたオブジェクトのUUID
 }

やや駆け足な感はありますが、rezについてはこれで一通り説明しました。
llRezObject()はまるで魔法のようにオブジェクトを出現させることができるので、使い方によっては非常に表現の幅が広がります。
この記事では作りませんが、銃から発射される弾丸などもこの方法で出現させています。

では、また次回。