前: これが最初
ProtoFluxを広く浅く説明します。解説書というよりは読み物です。細かいところを読み飛ばしてざっくり読み進めて構いません。
ProtoFluxとは何か
ProtoFluxとはビジュアルプログラミング言語で、Resonite上でコーディングでき、アバターの表情、ワールド、ゲームなど、Resonite上で複雑なギミックを実装するために利用するものです。Resoniteの開発チーム(Yellow Dog Man Studios)が独自に開発しました。 Resonite上に存在するデータを計算し、文字通りそれらをつなぎ合わせることでプログラムを構築します。
ProtoFluxはビジュアルプログラミング言語で、C言語やPython、Javascriptのように文字だけを使ってプログラムを記述するものではありません。 ビジュアルプログラミング言語と聞くと「子供っぽい」「安っぽい」と思うかもしれませんが、ランタイム(実行環境、厳密には異なりますがResoniteそのものだと思って差し支えありません)が提供する多種多様な機能を利用することで技巧的、独創的なモノを作ることが可能です。
ProtoFluxで利用できる機能の例として
- ワールド上に存在するオブジェクトの操作、複製、削除、オブジェクトにアタッチされたコンポーネントの値の操作等による3D空間への干渉、制御、メッシュベイク、ワールド移動、アバターの着用など固有の機能
- HTTP(GET/POSTのみ)およびWebsocketプロトコル通信による外部サーバーとの通信
が挙げられます(アップデートによりさらに増える可能性があります)。
ProtoFluxには個人、集団を問わず開発をサポートするための機能がいくつかあります。以下でそのようなProtoFluxのいくつかの特徴を述べます。
データの流れを視覚化するノードプログラミング
ビジュアルプログラミング言語にもいくつか種類がありますが、ProtoFluxは「ノード」同士を「ワイヤー」で繋ぎ合わせてデータを加工する処理を記述する、いわゆる「フロー(流れ)型」に属するものです。(Scratchは「ブロック型」と言われます)
ProtoFluxでのプログラムの記述はフローチャート図とよく似ています。
なんだかよくわからないノードがたくさんあって複雑に入り組んでいます。 しかし、白っぽいワイヤー(▷▷▷▷)に注目して辿っていくと、
- 「一番左のノードで信号が発生し、Ifで分岐して、Writeノードが何かする」
ことが、なんとなくわかると思います。
何が起こっているのか
上の画像で登場したノード
- Button Events
- ノードに設定したボタン要素の状態変化に応じて信号を発生させるノード
- If
- 信号が入力されたとき、黒いワイヤーから入力される値(TrueもしくはFalse)に応じて信号の行き先を変えるノード
- Write
- 信号が入力されたとき、赤いワイヤーから入力される文字列を、矢印の先にあるVariableノードに書き込むノード
「矢印」について‣
上のProtoFluxの例では、左端の「Button Events」から信号が発生し、「If(入力値に応じて分岐する)」で入力値(Boolean型)の計算が行われ、TrueかFalseかに応じて分岐し、それぞれの分岐先にあるWriteノードがそれぞれ文字列を書き込みました。
「インパルスの伝達」と「数値計算」
上の画像には2種類のワイヤー(白っぽいもの、それ以外のカラフルなもの)があり、何かしらの情報を左から右へと伝達します。
ProtoFluxでノード同士を繋げるワイヤーは2種類あり、2つの機能は全く異なります。
ProtoFluxで扱う2種類のワイヤー
- ▷▷▷▷▷▷▷▷のような模様がついたワイヤー(淡い色であることが多い)
- 矢印の方向に信号を伝達し、接続先のノード固有のアクションを引き起こす、導火線のようなもの
- 特に模様が描かれていないワイヤー
- 数値などあらゆるデータを伝達するものです。
- 「▷▷▷」模様が描かれたワイヤーは、インパルスを伝達します。
- インパルスはほとんどの場合押した時点のフレームで処理が完了します。
- フレームを跨いで処理は続きません
- ただし、意図的に遅延を発生させたり、処理が短時間で終わらない特殊なノードは遅延が発生します。
- Resonite内でアクションを引き起こすノードは、インパルスを受け取った時点で入力値の計算を行い、その機能を発動します。
- 特に模様が描かれていないワイヤーは、データを伝達します。
- 左側から送られてきたデータに何かしらの処理をし、右側から出力します
- ノードからノードへデータが渡される際も、フレームを跨がずその瞬間の値が次々に渡されるので、遅延は発生しません。
強力なデバッグ機能と「“Hello World”」
ResoniteのSteamストアページではProtoFluxの特徴の一つとして
- 集団開発を支援するための即時的なデバッグ機能
が挙げられています。
ProtoFluxの「ゲーム内でスクリプトを組む」という仕様そのものが強力なデバッグ機能とも言えますが、もっと具体的な値を簡単に表示する機能が存在します。
デバッグ画面に「Hello World!」と表示する、プログラミング言語を学ぶ際の作法でProtoFluxのデバッグ表示を見てみましょう
- ノードの出力内容を確認したいときは、出力からワイヤーを伸ばしたままセカンダリを押します。
- 「Display」ノードが出現します。
- 「Display」ノードは、入力されたデータを表示します。
表示形式はDisplayノードのデータ型によって異なります。
- Stringはそのまま
- Color型は色と数値
- Slot型はSlotオブジェクトの内容
- SlotはResoniteのワールドを構成する最小の要素です。
- Unityでいうところのゲームオブジェクトです。
を表示します。
すぐわかるProtoFlux
ProtoFluxもプログラミング言語の一種ですから、他のプログラミング言語で使う概念がProtoFluxに登場し、また逆にProtoFluxで学んだことを他に活かせることもあります。 ここでは、色々なプログラミング言語で使われる
- データ型
- 変数
- 演算子
- イベント
を本当にざっくり説明します。
データ型
ProtoFluxでは、
- データを伝えるワイヤー
- ノードにあるワイヤーを接続する部分、コネクタ
には色がついています。ワイヤーの色によって中を通るデータの種類が違います。
このデータの種類のことをデータ型と言います
データ型は、例えば足し算をするときに
- 「数字」の足し算をするときは、数字をそのまま足す
- 「文字」の足し算をするときは、文字と文字をつなげる。
と、区別できます。
ProtoFluxでは、このようなデータ型を
- 色
- 簡単な模様
で区別します。
以下はResoniteおよびProtoFluxで利用できる典型的なデータ型のリストと、それぞれの見た目です。
型名 | データの種類 | Resonite内での使用例 |
Boolean | TrueまたはFalse。1か0 | Slot(オブジェクト)のオンオフ |
Float | 実数値。符号付32bit浮動小数点数 | 3Dモデルのシェイプキーの程度 |
Int | 整数値。符号付32bit整数 | |
Float3 | Floatを3つ組合わせたもの | オブジェクトの座標 |
FloatQ | 四元数 | オブジェクトの回転 |
ColorX | 色と色空間 | マテリアル等の色 |
- Float3のワイヤーの見た目は、Floatを3つ束ねたような見た目になっています。
- Float3に限らず、複数の数字の成分を持つベクトル型は、bool2やint4のように型の名前が「スカラー型名[数字]」となります。
- FloatQのinputノードは、オイラー角を書き込むようになっていますが、Displayノードは四元数のそれぞれの係数が書かれており、表示される情報が異なることに注意してください。
このように、ProtoFluxではデータ型の違いを言葉だけでなくに色と模様でも区別できるため、プログラミング初心者が陥りがちな求められたものと違う型を渡してしまうことによるエラーが発生しづらくなっています。
また、異なるデータ型で、キャスト(変換)しようのない場合はそもそもワイヤーがつながらないようになっています。
以上のしくみにより
- 「なんか『Type ‘string’ is not assignable to type ‘number’』って出たんですけど!?なになになに!?」
といった初心者が陥りがち(そして挫折しがち)なエラーはそもそも発生しないようになっています。
変数
ProtoFluxでは3つのタイプの変数を定義できます。
- Local
- インパルス発生時に宣言され、終了時に破棄されるローカル変数
- Store
- ノード内に保存され、ユーザーごとに異なる値を持つ変数
- Data Model Store
- ノード内に保存され、セッション内で完全に同期される変数
特にProtoFluxを触りだしてから日が浅いうちはとりあえずData Model Storeを選択することを推奨します。
変数は多くのプログラミング言語では基礎中の基礎ですが、ProtoFluxでこれらの「変数」を使う場面はあまり多くないのでここではあまり深く掘り下げることはしません。
基本的な演算子
ノードブラウザの「Operators >」カテゴリにあります。
- Operatorsは日本語で演算子という意味です。
よく使う演算子も数あるノードの一つに収まっているので、いちいち取り出さなければなりません。(サードパーティ製のノードブラウザによくつかうノードをすぐ取り出せる機能がついたものがありますが)
また、ノード名が記号ではなく全て英語で表記されているため、初見ではなかなか目当てのノードが探しづらくなっています。(検索機能もないので)
以下に典型的な演算子のリストを記します。
演算子 | ノードブラウザ上の表記 | 一般的な表記 | 説明 |
加算(足し算) | Add | + | 数字を足したり、文字列を繋ぎ合わせます |
減算(引き算)
乗算(掛け算)
除算(割り算) | Sub
Mul
Div | -
*
/ | それぞれ算術計算をします。
一部のデータ型では特殊な計算をします。(floatQ、matirx型など) |
等号 | Equals | == | 二つの値が等しいかどうか、TrueかFalseを出力します。 |
この他にも様々なデータ型に対応した演算子があります。詳しくは別な場所で説明します。
イベント(インパルス)
アクションを受け取って駆動するタイプの処理について説明します。
インパルスの引き金となる動作の例は
- ボタンが押される
- 何かしら値が変化する
- セッションにユーザーが入る/退出する
などが挙げられます。
インパルスによって駆動する処理の例は
- 値をどこかに書き込む
- 指定した音源を鳴らす
- どこで、どんな音量で、音の距離減衰の種類は何か、などを設定できます。
- ユーザーやオブジェクトをテレポートさせる。
- アバターを着せる
- カメラの撮影をする
- HTTPリクエストを送信する
などが挙げられます。
次のProtoFluxの例でインパルスの動作を説明します。
これは
- ユーザーがjoinしたとき、変数Noticeに「〇〇さんが入室しました!」と書き込む
だけのFluxです。順番に処理を追っていきましょう
- (Userがjoinし、)User Joinedからインパルスが発火する
- Writeに入力され、Writeにつながっている値の計算が始まる
- 一番左端の「JoinedUser(user型)」から入ってきたユーザーが出力されます。
「UserJoined」のようにインパルスの出力と一緒に出力されるデータ(ここではピンクのUser型)は
- 「そのノードから出されるインパルスによる処理でのみ取得できる」データ
と言うような振る舞いをします。
ですので、JoinedUserの内容を表示するDisplayノードは常にnullが表示され、有効な値が表示されることはありません。
- インパルスと一緒に出てくるデータを確認したい場合はDisplayノードではなく、「Writeノード」と「DataModelStoreノード」を組合わせる必要があります。
インパルスと同時に出力されるデータをデバッグ表示する方法。