Yes Second Life

セカンドライフ向けWebサービスを作ってました。このブログではVR・メタバースのことを書いていきます

LSLスクリプトでJSONを扱う(単要素処理編)

これは、セカンドライフ 技術系 Advent Calendar 2013向けに書かれた記事です。LSLにJSONを扱う関数が追加されたので、今回はそれを紹介します。

JSONとは

JSONはJavascriptの記法で書かれたデータなのですが、いろんなプログラミング言語にJSONを扱うためのライブラリがあるので、さまざまなプログラム間でデータをやりとりするときに使われています。

こんなかんじでオブジェクトと配列の組み合わせでJSONは構成されます。

// JSONオブジェクト
{ "a" : 1, "b" : true } 

// JSON配列
[ "c", 3, false ]

// 組み合わせ
[ "c", 3, false, { "a" : 1, "b" : true } ] 

LSLには「値を1つずつ処理する方法」「JSONをリストに一括で変換する方法」の、2通りのやり方が用意されています。一気に紹介しようと思ったのですが、意外と長くなってしまったので、今回は値を1つずつ処理する方法を紹介します。

llJsonGetValue

string llJsonGetValue(string json, list specifiers)

JSONから指定したパスにある値を文字列として取得します。第一引数に対象のJSONを指定して、第二引数のListでパスを指定します。

// JSONをリテラルで書く場合、ダブルクォーテーションはエスケープが必要です
string value1 = llJsonGetValue("{ \"a\" : 1, \"b\" : true }", ["a"]);

// 1と表示されます
llOwnerSay(value1);

// ネストした例、配列の4番目(0から始まるので)のオブジェクトの、bをKeyにもつ値を取得
string value2 = llJsonGetValue("[ \"c\", 3, false, { \"a\" : 1, \"b\" : true } ]", [3, "b"]);

// TRUEと表示してほしいところですが、﷖と表示されます
llOwnerSay(value2);

2つめの例をみるとわかるように、リストにパスとなる値を書いていくことで深い位置にある値もとってくることができます。しかし、うまくTRUEと表示されてくれません。LSLには定数として「TRUE」が用意されてるんですが、これって単に数値の1の置き換えでしかないので、実は真の意味で真偽値を表す定数ってないんですね。そこで、JSONの真偽値を表すために「JSON_TRUE」「JSON_FALSE」が追加されています。

// trueを取得します
string value1 = llJsonGetValue("{ \"a\" : 1, \"b\" : true }", ["b"]);

// このように、条件分岐を使うと人にもわかるように表示できます
if(value1 == JSON_TRUE)
{
    llOwnerSay("TRUEを取得しました");
}

定数は他にもあります。

// nullを取得します
string value1 = llJsonGetValue("{ \"a\" : 1, \"b\" : null }", ["b"]);

// nullは、JSON_NULLであらわします
if(value1 == JSON_NULL)
{
    llOwnerSay("NULLを取得しました");
}

// 存在しないKeyを指定します
string value2 = llJsonGetValue("{ \"a\" : 1, \"b\" : null }", ["c"]);

// JSON_INVALIDが返ります
if(value2 == JSON_INVALID)
{
    llOwnerSay("不正な操作です");
}

llJsonSetValue

string llJsonSetValue(string json, list specifiers, string value)

当然値をセットする関数もあります。第一引数に対象のJSONを指定して、第二引数のListでパスを指定、第三引数でセットする値を指定します。返り値は値が更新されたJSONです。

// aをKeyとする値に数値の2をセットしています
string value1 = llJsonSetValue("{ \"a\" : 1, \"b\" : true }", ["a"], "2");

// {"a":2,"b":true}と表示されます
llOwnerSay(value1);

// ネストした例、今度は文字列の2をセットしています
string value2 = llJsonSetValue("[ \"c\", 3, false, { \"a\" : 1, \"b\" : true } ]", [3, "a"], "\"2\"");

// ["c",3,false,{"a":"2","b":true}]と表示されます。「数値」と「数字の文字列」は区別されています
llOwnerSay(value2);

// aをKeyとする値にオブジェクトをセットしています
string value3 = llJsonSetValue("{ \"a\" : 1, \"b\" : true }", ["a"], "{\"c\":1,\"d\":2}");

// {"a":{"c":1,"d":2},"b":true}と表示されます
llOwnerSay(value3);

// 存在しないKeyを指定すると、キーと値のペアを追加できます
string value4 = llJsonSetValue("{ \"a\" : 1, \"b\" : true }", ["c"], "3");

// {"a":1,"b":true,"c":3}と表示されます
llOwnerSay(value4);

数値と数字の文字列が区別されたり、オブジェクトをセットできたり、けっこう自由度が高いです。また特殊な定数を使った便利な操作も用意されています。

// JSON_NULLを使って、nullをセットしています
string value1 = llJsonSetValue("{ \"a\" : 1, \"b\" : true }", ["a"], JSON_NULL);

// {"a":null,"b":true}と表示されます
llOwnerSay(value1);

// JSON_APPEND定数を使って、配列の最後に値を追加しています。要素数がわからないとき便利です
string value2 = llJsonSetValue("[ \"c\", 3, false, { \"a\" : 1, \"b\" : true } ]", [JSON_APPEND], "5");

// ["c",3,false,{ "a" : 1, "b" : true },5]と表示されます
llOwnerSay(value2);

// ネストした配列でも可能です
string value3 = llJsonSetValue("[ \"c\", 3, false, [ \"a\", \"b\"] ]", [3, JSON_APPEND], "6");

// ["c",3,false,["a","b",6]]と表示されます
llOwnerSay(value3);

// JSON_DELETE定数を使って、値を削除しています
string value4 = llJsonSetValue("{ \"a\" : 1, \"b\" : true }", ["a"], JSON_DELETE);

// {"b":true}と表示されます
llOwnerSay(value4);

// 配列でも削除できます
string value5 = llJsonSetValue("[ \"a\", \"b\"}", [0], JSON_DELETE);

// ["b"]と表示されます
llOwnerSay(value5);

llJsonValueType

string llJsonValueType(string json, list specifiers)

指定したパスにある値のタイプを取得します。第一引数に対象のJSONを指定して、第二引数のListでパスを指定します。返り値は、以下の定数のどれかです。

  • JSON_INVALID
  • JSON_OBJECT
  • JSON_ARRAY
  • JSON_NUMBER
  • JSON_STRING
  • JSON_NULL
  • JSON_TRUE
  • JSON_FALSE
string json = "[ \"c\", 3, false, { \"a\" : null, \"b\" : true } ]";

// JSON_STRING
string type1 = llJsonValueType(json, [0]);
if(type1 == JSON_STRING) llOwnerSay("string");

// JSON_NUMBER
string type2 = llJsonValueType(json, [1]);
if(type2 == JSON_NUMBER) llOwnerSay("number");

// JSON_TRUE
string type3 = llJsonValueType(json, [3, "b"]);
if(type3 == JSON_TRUE) llOwnerSay("true");

// JSON_NULL
string type4 = llJsonValueType(json, [3, "a"]);
if(type4 == JSON_NULL) llOwnerSay("null");

// JSON_OBJECT
string type5 = llJsonValueType(json, [3]);
if(type5 == JSON_OBJECT) llOwnerSay("object");

// JSON_INVALID
string type6 = llJsonValueType(json, [9]);
if(type6 == JSON_INVALID) llOwnerSay("invalid");

以上で、単要素処理編はおしまいです。しかしJSONのパスをリストで表すというのが、なんか斬新でした。次回、一括変換編は万一アドベントカレンダーが完走しなかった場合に書こうとおもいます。ま、まあきっと完走するよね・・・。

LSLの文法「型」

この記事は、セカンドライフ 技術系 Advent Calendarの、10日めの記事です。

いま、消えそうな言語ナンバーワン、LSLの文法について書いていきます。今日のお題は型です。

LSLは、次の型があります。

  • integer(整数型)
  • float(浮動小数点型)
  • string(文字列型)
  • key(識別子型)
  • list (リスト型)
  • vector(ベクトル型)
  • rotation(回転型)

オブジェクト等の固有IDを表す「key型」、オブジェクトの大きさ・速度などを表す「vector型」、回転を表す「rotation型」等が、基本型に含まれてるのが特徴です。

integer型

−2,147,483,648 〜 +2,147,483,647の範囲をあらわす、4バイト整数です。

float型

1.175494351E-38 〜 3.402823466E+38の範囲をあらわす、浮動小数点数です。

string型

ごくごく一般的な文字列型です。「+」記号で連結します。

例:string value = "abc" + "def";

key型

セカンドライフのオブジェクトの識別子などに使われる型。ぶっちゃけUUIDです。

例:key value = "00000000-0000-0000-0000-000000000000";

list型

いわゆるリストです。要素に複数の型を混在させることができます。リストの入れ子はできません。ちなみに、LSLには配列はありません。

例:list value = [ 6, 1.8, "string" ];

vector

float型3つからなる型。3D空間を扱うLSLでは何気に便利な型です。オブジェクトの位置、大きさ、速度なんかを表すのにつかいます。

例:vector value = <1.0, 2.0, 3.0>;

rotation型

回転型です。LSLの回転は4つの数字からなるクォータニオンで表します。クォータニオンはちょっとややこしい概念ですが、この形式にすることで回転の合成などが簡単になります。

例:rotation value = <0.0, 0.0, PI, 1.0>;

まとめ

全体的に、3Dを扱うのに特化した型になってるのがわかるとおもいます。ぼくは経験ないですが、ゲームプログラミングなどをしてると理解しやすいのかもしれません。

セカンドライフ、LSLスクリプトでできること

今年は、層の薄いセカンドライフのクリエイターが集まって、アドベントカレンダーに挑戦することになりました。これは、その1日目の記事になります。

セカンドライフ 技術系 Advent Calendar

初日だしHelloWorld的なプログラムをつくろうかと思ったんですが、そもそも文法の前にLSLはどんなことができるのか知っておいてもらったほうが、プログラムの説明も簡単になる気がしたので、今回はLSLでできることをパーッとあげてみることにします。

チャット、通信

セカンドライフでは、アバター同士がチャットで会話できますが、オブジェクトにチャットさせることもできます。「○○さんが入店しました〜」みたいな通知に使ったり、自分の作品をプリムに説明させたり、応用次第でいろいろ使えます。

また、アバター会話用以外のチャンネルをつかえば、裏でオブジェクト同士でメッセージを交換させるみたいな、イベントドリブン的な制御にも使うことができます。

プリム、オブジェクト操作

セカンドライフのものつくりはプリムが基本になります。プリムは立方体、円柱みたいな原始的な立体で、それを複数組み合わせてオブジェクトをつくります。

LSLでは、これらを動かしたり、色やテクスチャを変えたり、大きさを変えたり、パーティクルを放出させたり、いろんな操作をおこなえます。LSLスクリプトの効果を見た目で実感しやすいので、とりあえずLSLを試してみたい時にオススメです。

アバター操作

アバターを踊らせたり、装飾品を装着させたりできます。これも、見た目で実感しやすく試してみたい時にオススメです。

カメラ操作

カメラ、つまりクライアントビューワの視点を制御できます。なかなか使いドコロがむずかしいですが、仮想世界の映像をそのままムービーにする「マシネマ」なんかでは、かなり活用されています。

FPSゲーム向けにマウスルックモードに移行することもできます。

メディア制御

昔はセカンドライフ上のメディアは貧弱でしたが、最近はプリムの表面に、ムービーを流したり、HTMLを表示したりといったこともできるようになりました。映画館をつくるみたいな当たり前の用途から、セカンドライフと連携するWebサービスをつくって、そのHTMLをプリムに表示みたいな応用まで、かなり面白い使い方をされています。

検出(タッチ、衝突、センサー)

LSLは、プリムがアバターにタッチ(クリック)されたり、衝突されたりしたのを検出できます。これを使えば、ボタンにタッチした人にダイアログを表示するとか、衝突してきた人を吹き飛ばすみたいなことが可能です。

また、センサー機能で近くにいるアバター群を検出することもできます。

持ち物関連

各アバターは持ち物を持っています。LSLで特定のユーザにアイテムを送ったりすることが可能です。

また、アバターだけでなくプリムもアイテムを持つことができます。たとえば宝箱の形をしたオブジェクトに、金貨を入れておくみたいな感じで使えます。LSLでプリムの中のアイテムを消したり、他のプリムにアイテムを渡したりなど、いろんな操作がおこなえます。

土地の管理

セカンドライフの重要な概念として、土地があります。LSLで土地の起伏を調整したり、土地のプリム数をカウントしたり、いろんな管理ができます。

また、LSLから特定のユーザをBANしたりすることも可能です。

乗り物

物理関連の関数を使うだけでも乗り物はつくれるのですが、LSLには専用の関数があります。車だけでなく、ボート、飛行機、気球など様々なタイプの乗り物がつくれます。

HTTP通信

LSLは、HTTP通信の機能も備えています。HTMLを取得して、文字列操作で欲しい情報を抜き出したり、直接WebAPIを叩いたりなど、いろんな使い道があります。最近では、独自のWebサービスをつくって、プリムと連携させるような高度なやり方も増えてきました。

また、HTTPリクエストをだすだけでなく、HTTPリクエストを受け取ることもできます。プリムがWebサーバになってしまうわけですね。プリム間でHTTPリクエストを送り合って自律的に動作させたりすることも可能で応用範囲は広いです。

まとめ

セカンドライフはネット上にほとんど情報がでてなくて、なにができるのかそもそも分からない人が多いとおもいます。上記にあげたのは、まだ一部分で細かくみてけば、他にも色々できることはあります。へー、こんなことができるんだと少しでも興味を持っていただけたら幸いです。

現役セカンドライファーが見ている世界、昨今の言説をみて思うこと

ネットで話題になるのは「セカンドライフの中は、まだこんなにひどかった」みたいなブログ記事ばかりで、いささか残念なんですが、あれはネタでやってる面もあるので、細かいツッコミを入れても仕方ない気もします。

むしろ、昔セカンドライフの悪い点をあげた記事に、顔を真っ赤にして反論してしまってるのが、かえって印象を悪くしてたような気がします。

だから、いちいち挙げられた点に反論するより、なぜぼくがいつまでもセカンドライフをやっているのか、どこに可能性を感じているのか書いてみたほうがいい気がしてきました。

1,Yahoo、Googleになれるチャンス

今、ネットで「オレはYahoo、Google級のサービスを作ってやる」とか言ってる人は現実を見たほうがいいです。ネットは初期に成功した企業が大きな力をつけて業界はもう固まってしまいました。大きいプラットフォームをつくろうと思っても、もはや不可能なので、「ニッチをねらう」ことが、ネットサービスのセオリーにすらなっています。

逆に仮想世界は、それ自体がなくなってしまう可能性もありますが、Google級のサービスをつくれる可能性もたしかにあります。自分で未踏の地を切り開くのは大変ですが、力のある人なら、これほどやりがいがあることもないと思います。

この可能性の大きさが仮想世界の魅力です。

2,コンテンツは仮想世界でしか売れなくなる

こちらは、ちょっと具体的なこと。ぼくが仮想世界で描いてるビジョンの中でも、とりわけ大きな話です。笑う人もいるかもしれないですが、まじめに考えてます。

いま、コピーフリーなネットがコンテンツ産業を破壊する問題は、いよいよ切羽詰まったところにきています。どんなにコンテンツを作ってもコピーが容易になったため、新たなビジネスモデルを考えなければいけないと、みんな言っています。しかし、結局出てくるモデルは「コンテンツを囲い込んで課金する」という、技術の進歩によってできるようになったことをあえて制限するような、退行したものばかりです。

「できることをあえて制限する」「今までできてたことをできなくする」そんな後ろ向きな解決を選びつつあるのが現状ですが、ぼくは、まったく新しいビジネスモデルを作って前向きに解決することができると考えています。そしてそのカギは仮想世界にあります。

ちょっと考えてみてください。コンテンツを売る前向きな解決策として、「ライブで収益をあげる」という考え方があります。ライブの体験はコピーできません。グッズを売るのももちろんそうですが、家でいつでもコンテンツを消費するのとは違った、そのときしかできない体験にお金を払ってもらうわけです。

ぼくは、これはすばらしい解決策だと思います。しかし、残念ながらこのモデルが成り立つのは東京だけなのです。よほどの大手でないかぎり、ライブは東京でしか行われないので、地方の住民は移動コストというハンデがあるのです。では、この移動コストがなくなったらどうでしょうか?

仮想世界でヴァーチャルライブを行い、自宅の部屋から参加する

これが、コンテンツ問題を前向きに解決できる、唯一の解だとぼくは考えています。そして、これを実現するには色々やらないといけないことがあります。

  • HMD、脳波コントローラ、ヘッドセットなど没入型インターフェースの普及
  • 仮想世界の安定性の向上
  • 日本的デザインをもっと作りやすく(メッシュインポートでかなり改善された)
  • 表情連動などの機能追加

まだまだハードルは高いですが、ヴァーチャルライブの台頭は、仮想世界の勃興だけでなく、コンテンツ問題の解決にもつながり、いつかはこの流れがくると思っています。

リアルな人間じゃなくアバターでいいのかという人もいると思いますが、もともとアイドルなんかは偶像なわけでアバターのほうが都合がいい面もあります。またリアルの生々しさがないぶん、3Dエフェクトみたいな仮想世界でしかできない演出というのもあります。

好きな音楽をデータでなく仮想世界上の生の歌手から聞く。尊敬してるイラストレータの絵をみるだけでなく仮想世界上で自分の似顔絵を描いてもらう。未来の有料コンテンツはすべてライブ化します。なかでも、「声優のボイスチャット+キャラクターのアバター」で行うライブはキラーコンテンツになるでしょう。

未来をみてほしい

今回ぼくが書いた話は荒唐無稽に聞こえるかもしれません。まだ実現してない先のことを語っているのでしかたないのですが。

セカンドライフがネットで話題になるとき、こんなにしょぼい、すぐ落ちる、みたいな感じになりますが、ぼくもそう思います。現状の仮想世界はしょぼすぎる。でも未来もそうだとはおもいません。セカンドライフメッシュインポートなど、様々な進歩をしています。

ネットの言説は、仮想世界がいつまでも進化しないとおもって書かれたものが多いです。未来にどうなっているのか、未来の仮想世界をどうしていくのか。そういった建設的な話をみてみたいです。

AR in VR カソウセカイカメラをリリースしました

f:id:sabro:20120802165258p:plain

まったく手応えがないままに、セカンドライフ向けサービスを作り続けているわけですが、ついに第3のサービスをリリースしました。

ARとVRの先端技術を組み合わせれば、とにかくすごいんじゃね? という安易な発想のもと、仮想現実の中で拡張現実が楽しめるものがいいだろうということで、できたのがカソウセカイカメラです。

カソウセカイカメラ
http://www.kasousekaicamera.com/

詳しくは、発表会の資料をご覧ください( ̄∇  ̄ )

なぜ今仮想世界なのか?セカンドライフに訪れた3つの変化

セカンドライフ

セカンドライフに人生を賭けるという、人生最大の失敗を犯してから、4年が経ちました。

しかし、石の上にも三年とはよく言ったもので、最近は仮想世界の可能性を感じさせる変化が見られるようになってきました。今回は、最近のセカンドライフに起こった3つの変化を紹介します。

変化1 一般的な3DCGをそのままインポート可能に

長い間、セカンドライフは"プリム"と呼ばれる単純な図形を、複数リンクさせることで複雑なオブジェクトを作成する制作スタイルを貫いて来ました。これは初心者には作りやすくていいのですが、3DsMax、Maya、Blenderなどの高度なツールを使いこなせる上級者からみると、もどかしい部分がありました。しかし、今年の8月、リンデンラボはメッシュインポートという機能をリリースし、一般的な3DCGで使われるCollada形式の取り込みを可能にしました

Colladaは非常に一般的な形式なので、変換ツールなどを使えば、世にあるほとんどの3DCGは取り込むことができます。3Dモデルをアバターとして使うことも可能で、MMDモデルなんかもColladaに変換してボーンとの関連付けをやりなおせば、インポートして自分のアバターにできます。MMDのダンスデータもセカンドライフの形式に変換するツールがあるので、まさにニコニコ動画MMDを踊らせてる動画のようなことを、セカンドライフでも再現できます。しかも眺める側でなく踊る側でです。

変化2 メタバース連動Webサービスの台頭

オブジェクトを作ってそれにスクリプトを仕込む程度の制作物が長い間主流になってましたが、最近はWebとうまく連携させた制作物が増えてきました。元々、セカンドライフスクリプトであるLSLには、HTTPを扱える関数があるので、外部のWebサイトとの連携が可能だったのですが、ようやくそのノウハウがたまってきたようです。

セカンドライフは、人が集まってる時間帯がわかりづらく、ログインしても誰もいないということがよくあったのですが、それを解決するために生まれてきたのが、次に紹介する「すりんく」や「LIVES」のような、今盛り上がっているところを探すサービスです。

すりんく すりんく
すりんくが配布しているオブジェクトを自分の運営するカフェなどに設置すると、センサースクリプトが今まわりにいるユーザ数をカウントします。そして、HTTPでサーバに転送し、人がいる場所をトップページヘ表示する仕組みになってます。

 

LIVES LIVES
すりんくに仕組みが近いですが、にぎわってる場所をWeb上で確認するのではなく、自分のアバターの周りに近未来っぽく展開します。

エンターテイメント向けのサービスもあります。セカンドライフは自由すぎて目的がないとは、よく言われてきましたが、目的をリンデンラボではなく、クリエイターが作り始めています。

クリエモン クリエモン
目、鼻、口などの表情パーツをWeb上で投稿・共有し、それらを組み合わせて自分のアバターの表情を作れるサイトです。お気に入りに登録した表情は、セカンドライフ内のガジェットにロードできます。"セカンドライフ萌えおこし"が、ミッションらしいです。

 

クエストマイスター クエストマイスター
Web上で情報を入力して、専用のストーンをセカンドライフに設置するだけでクエストが作れるサイトです。クリア条件をLSLスクリプトで設定することも可能なので、工夫次第でいろんなクエストが作れます。

"人が集まってるところが分からなくてログインしても誰もいない" "自由すぎて遊ぶ目的がない" みたいな、バブルの頃によく言われていた欠点が、Webを上手く活用することで解決されつつあります。ちなみに、上記の4サイトは、企業ではなく、どれも個人クリエイターが製作しています。つか、下2つは僕が作りました。

変化3 ビジネス目的の企業が撤退

セカンドライフで儲けたいみたいな企業は大抵撤退しました。まだいくつか企業も残ってますが、セカンドライフバブルにのっかりたいというよりは、自分たちの力で面白くしてやろうという志の高いところが残ってる感じです。

世の中では、企業が撤退してクリエイターの天国になっているみたいな認識をしている人も多いですが、クリエイター以外の人も多いです。セカンドライフのユーザを乱暴に3つに分けると次のような感じになります。

  • アバターの着せ替え機能を活用する、ファッション好きのユーザ
  • セカンドライフを高度なチャットツールとして活用する、おしゃべり好きのユーザ
  • 仮想世界での制作に魅了されたクリエイター

セカンドライフは女性ユーザが多いと言われますが、やっぱりファッション、チャット目的のユーザが大半で、クリエイターは少数派です。しかし、少数だからこそ、制作能力のある人は非常に重要視されますし、活躍の場は多いです。ネットの個人サービスはもう飽和してしまって、一週間くらい流行って終わりみたいな感じになっちゃってますが、セカンドライフなら、個人でも仮想世界を代表するようなサービスを作るチャンスがあります。ビジネスの人達がいなくなった今こそ、個人制作の面白いサービスがでてくる下地ができたといっていいでしょう。

オフィスアワー会場 毎週月曜日の22時から、セカンドライフで意識の高い()ユーザの集まりをやってるので、ここまで読んで、興味が湧いた人は、よろしければ一度話を聞きにいってもおもしろいとおもいます。
集合場所(セカンドライフ
http://maps.secondlife.com/secondlife/Trinity/12/138/22