メインコンテンツまでスキップ

このエンジンを選ぶ理由

機能の一覧ではありません。作れるものを変えてしまう、ごく少数の設計判断と、それが実務でなぜ効くのか という話です。

どこでも同じ 1 つのモデル

エディター、ウェブのプレイヤー、スマートフォンのアプリ、サーバー。そのすべてが同じシーンを 動かします。同じオブジェクト、同じ component、同じ挙動です。

エクスポート工程はなく、別の「ランタイム形式」もなく、片方からずれていく 2 つ目の実装もありません。 エディターで並べたものがそのまま動き、プレイヤーで見つけた不具合はどこでも再現します。

実務上の帰結は、地味ですが価値があります。公開しても、ものの意味が変わりません。

グラフはインタープリターではなく、コードになります

多くのツールでは、ビジュアルグラフは実行時に何かがノードごとに、毎フレーム辿るデータです。ここでは 一度ふつうの script にコンパイルされ、動くのはその script です。

速度グラフのコストは手書きのコードと同じです。グラフがコードそのものだからです
中身が見えるコードパネルを開けば、グラフが何になったかをそのまま読めます
組み合わせられるグラフから script を、script からグラフを呼べます。下では同じものだからです

だから「ここから先はビジュアルツールを捨ててコードで書き直し」という天井がありません。いまある グラフの隣に script を足すだけです。

マテリアルは、底までグラフです

組み込みのマテリアルの種類は、ノードエディターを後付けした固定セットではありません。独自グラフが 使うのと同じ体系の中の一点です。だからグラフのマテリアルは遅くもなく、二流でもなく、ウェブに 限られてもいません。同じグラフが、ブラウザー用にもスマートフォンのネイティブレンダラー用にも コンパイルされます。

そして使っていないものはコストゼロです。既定値のままの physical の追加項目はコンパイル時に 畳み込まれるので、ガラスにできる選択肢を持つマテリアルは、持たないものとまったく同じ安さです。

表計算ソフトのように動きます

ほかのすべてが乗っている判断がこれで、たとえ話がいちばん分かりやすいはずです。

表計算では、セルを 1 つ変えると、そのセルを使っている数式だけが再計算されます。シート全体を 計算し直す人はいませんし、「更新」ボタンを押すこともありません。

シーンもまったく同じです。 オブジェクトの色を変えたとき反応するのは、その色を読んでいたもの だけです。オブジェクトではなく、です。

変更  material.color

├─ レンダラーがその面を塗り直す
├─ それを表示していたインスペクターの欄が更新される
├─ 変更が共同編集者向けのキューに入る
└─ …そのほかには何も実行されない

それで何が得られるか

ポーリングもしませんし、念のための再描画もしません。 何が動いたかを見つけるために、世界を 自分のコピーと比べる毎フレームのパスは存在しません。フレームは変更が要求した仕事だけを行い、 止まっているシーンのコストはほぼゼロです。

大きなシーンでも、編集中に反応が鈍りません。 2 万件のキーフレームを持つタイムラインは、 そのうち 1 つが動いたからといって描き直されません。パネルは、リストの全キーフレームを購読せずに 「キーフレームが変わった」ことだけに依存できます。大きなプロジェクトが実用に耐えるのは、この 違いのおかげです。

読み込みに、読み込み用のコードは要りません。 system はリソースを要求し、まだ届いていなければ 何も返りません。届いたら、system がもう一度走るだけです。コールバックを書く人も、準備完了フラグを ポーリングする人も、「まだ読み込まれていない」場合を二度書く人もいません。

1 本の変更の流れが、すべてを養います。 レンダラー、インスペクター、undo、共同編集者、script の サンドボックス、物理シミュレーション。すべてが同じ更新を読みます。だから互いにずれることも、 シーンの中身について食い違うこともありません。undo も特別扱いの経路ではなく、同じ管を通る もう 1 つの変更です。

エンジンに伝え忘れることができません。 「dirty を立てる」も「refresh」も、覚えておくべき手動の 無効化もありません。値を書くことが、そのまま通知です。

書き込みかたも丁寧です

値の更新は、置き換えではなく、すでにあるものへのマージです。だから見ていたものは、見ていた対象に つながったままです。実装の細部に聞こえますが、これはなめらかなアニメーションと、シーンが大きく なるほど落ちていくフレームレートとの違いです。

フレームワークの機能ではなく、土台です

リアクティビティは独立したパッケージで、同じものがあなたにも使えます。プラグインのパネル、 component の拡張、そしてエディター自身のインスペクターも、すべてこれで書かれています。あなたの 書いた拡張が更新される理由は、組み込みのパネルとまったく同じです。

import { signal, computed, effect, batch } from '@was/signals';

const score = signal(0);
const label = computed(() => `Score: ${score.value}`);

effect(() => render(label.value)); // スコアが動いたときだけ再実行される
batch(() => { score.value += 1; score.value += 1; }); // 更新は 2 回ではなく 1 回

3 つの性質には名前を与える価値があります。たいていのリアクティブな仕組みは、そのうち 1 つか 2 つ しか持っていないからです。

細粒度依存は読んだ値ごとに追跡され、component 単位ではありません。「念のため」の再描画は起きません
深いオブジェクトのツリー全体がリアクティブになるので、position.y を見ることはオブジェクトを見ることとは違います
依存が安い何かが変わったことに、それを読まずに依存できます。1 件動いただけで巨大なリストが再描画されないのは、これのおかげです

最後のものは地味に聞こえますが、2 万件のキーフレームを持つタイムラインが編集可能なままである 理由がこれです。

共有パッケージ

1 フレームも食わないバリデーション

どの component もスキーマで記述されます。そしてスキーマはふつう税金を伴います。データが届くたび、 実行時に何かが記述をフィールドごとに辿るからです。

ここでは、スキーマはその形に合わせたコードへ一度だけコンパイルされます。辿る処理はありません。 違いは学術的なものではなく、このプロジェクト自身のベンチマークで測った値です。

パースバンドルへの追加
よく使われるライブラリ(zod)1 回 94.7 ns最小化 +267 KB、gzip +61 KB
こちら(svdt)1 回 5.0 nsなし。すでに入っています

およそ 19 倍速く、来場者が追加でダウンロードするものもありません。

これが効くのは、ここでのバリデーションが稀なイベントではないからです。エディター、script の サンドボックス、物理シミュレーション、共同編集者のあいだを越えるすべての変更で走ります。1 項目 あたりでは無視できそうなコストも、毎秒何千回も起きればアニメーションの予算そのものになります。

これもあなたが使えます

自分のプラグインが自分のデータのために import できる、同じパッケージです。 → 共有パッケージ

重い仕事はフレームの外へ

ブラウザーのページを止めがちな 2 つを、外に出しています。

  • あなたの script はページから隔離されて動くので、遅いループが描画を凍らせることはありません
  • 物理はフレームの中ではなく、その隣で走ります

シーンは忙しいときでも反応し続けます。ロジックが面白くなってきた途端にフレームを落とす、という ことがありません。

ランタイムは、必要になるまで仕事を拒みます

これは来場者にとって、読み込み時間として現れる部分です。

物理は、シーンが本当に必要とするまで起動もダウンロードもされません。 動く部品のない書き割りが シミュレーターの代金を払うことはありません。それは来場者が待たずに済むメガバイトです。判定は 生きていて、セッション中に作られたボールは、自分のために物理を起動させます。

1 万個のコピーのコストは、ほぼ 1 個分です。 草、群衆、瓦礫、パーティクルは 1 回の描画で 済みます。その配置は保存ではなくシードから生成されるので、ファイルにもネットワークにもコストが かからず、どの参加者にも同じに見えます。

パーティクル単位のものが同期されることは一切ありません。 同じ設定はどこでも同じ効果を生むので、 凝った効果もマルチプレイヤーでは無料です。

挙動の語彙はひとつ

イベント・patch グラフ・script は、同じトリガーを聞きます。on-click は 3 つとも同じ意味です。 名前の体系を 1 つ覚えたら、あとはどれだけコードを書きたいかを選ぶだけです。

つまり、インタラクションをイベントとして始め、条件が要るようになったら patch に格上げし、本物の ロジックが要るようになったら script に移れます。何も学び直さずに。

1 人のために作られてはいません

共同編集は後付けの機能ではありません。space はそこにいる全員が共有する、生きたひとつの世界 なので、編集は起きるそばから現れ、undo は各自のものとして働きます。

同じ仕組みが、エディター・script のサンドボックス・物理シミュレーションを同期させます。だから それらがシーンの中身について食い違うことはありません。

あなたの観客がすでにいる場所で動きます

公開したプロジェクトは、リンクから、ブラウザーで、何もインストールせずに開きます。それが WebAR の要点です。アプリストアも、ダウンロードも、「まず私たちのアプリを入れてください」も、 来場者とあなたの作ったものとの間には入りません。

そこからさらに、同じプロジェクトが作り直しなしで遠くまで届きます。

どこへどうやって届くか
あらゆるスマートフォンのブラウザー公開リンク、または QR コード。インストール不要
iOS の App Clipリンク・QR コード・NFC から、App Store のインストールなしで開きます
ネイティブアプリネイティブレンダラー(下記参照)
ヘッドセットのブラウザー同じ公開リンク。ランタイムが WebXR を話します
AR グラスとヘッドセットXREAL One・Quest 3・PICO 4 向けのネイティブ XR レイヤー(下記参照)
Unity 経由のヘッドセットUnity SDK — XREAL、PICO、Apple Vision Pro、HoloLens 2、Magic Leap 2、Rokid
ポスターからコンテンツまでの最短路が App Clip です

コードにカメラを向けると体験が開きます。ストアもアカウントも待ち時間もありません。Apple はクリップの サイズに上限を設けているので、最初のシーンは軽くしておき、動き出してから残りを読み込んでください。

Unity SDK 経由のヘッドセット向けビルドは Enterprise のオプションです

スマートフォンは最初から動きます。デバイス固有のパッケージ — レンダリングパイプライン、 コントローラーのプロファイル、デプロイのテンプレート — はアカウント単位で付与されます。 → 対応プラットフォーム

スマートフォンでは、ネイティブの描画速度

ブラウザーでは WebGL が使えます。速いですが、天井があります。ネイティブアプリはブラウザーを まったく通さず、iOS でも Android でもネイティブレンダラーを使い、Metal と Vulkan に直接 話しかけます。

だから同じプロジェクトが、ネイティブアプリのグラフィックス予算を手に入れます。リアルタイムの影、 より重いマテリアル、画面上により多くのもの。しかも 2 つ目のバージョンを保守する必要はありません。 マテリアルはウェブ用と同じようにそのレンダラー用にもコンパイルされます。「同じプロジェクト」が 願望ではなく事実なのは、そのためです。

届く範囲のためにウェブ版を、フレーム予算が必要なプロジェクトのためにアプリを使ってください。

グラスにも、ネイティブに

ネイティブの XR レイヤーは、AR Clip のランタイムそのものをグラスに載せます。同じプロジェクト、 同じシーンが、ブラウザーではなくデバイス上で描画されます。

1 つのインターフェースに、差し替え可能なベンダーのバックエンドという形で作られているので、 デバイスはランタイムのフォークではなくバックエンドです。Unity は経由しません。

デバイス経路そこで動くもの
XREAL Oneベンダー SDK表示、ヘッドトラッキング、カメラ、セッション記録
Meta Quest 3OpenXR表示、トラッキング、コントローラー、ハンドトラッキング、セッション記録
PICO 4OpenXR同じ。ただしカメラはオフ
できることはデバイスごとに違い、ランタイムがそれを教えてくれます

バックエンドは、できるふりをせず、実際に対応しているものを申告します。PICO にはここでのカメラ パススルーがないので、背後に現実世界が必要なシーンは XREAL か Quest に置くべきです。必要ない シーンなら 3 つとも動きます。

来場者がどの経路で来ても、component も挙動も同じ、同一のシーンです。ウェブ版とヘッドセット版を 別々に保守することにはなりません。

そして、効く場所で拡張できます

独自のステップやトリガーは、アプリケーションから登録できます。エディターは プラグインを受け付け、パネルを足したり、シーンを生成したり、まったく新しい 種類の component を持ち込んだりできます。ノードのカタログには、唯一カバーしていない場合のための 非常口があります。

このドキュメントが古びない理由

このサイトにある component・トリガー・ステップ・ノードの表はすべて、エンジンそのものから生成 されています。エンジンにノードが増えれば、リファレンスに行が増えます。誰も更新を覚えておく必要は ありません。


次へ: オブジェクトとシーン — モデルの全体像。