2026年10月のリリース
先月、2.x には互換性を保つ変更だけを加え、次の互換性を損なう変更は 3.0 で行うと書きました。その変更が10月に入り、移行ガイドも用意しました。
10月、Turian はレンダラー付きのエディタから、ゲームを作れるエンジンへと変わりました。物が落ち、衝突するようになりました。カメラは見えているものだけを描画し、木箱を1万個複製しても描画呼び出しは1回です。デザイナーはアセットを使ってゲームの仕組みをつなげられます。スクリプトはコルーチンなしで2秒待てますし、ゲームはセーブできます。同じプロジェクトから、ウィンドウ付きのクライアントも、ウィンドウのないサーバーも書き出せます。そして、そのすべてを作るエディタ Studio にも、使い慣れた操作感の Scene ビューがようやく備わりました。

- なぜ 3.0 なのか
- 物が落ちる:3D 物理
- 描画を減らし、速くする
- ワールド内の線、軌跡、文字
- デザイナーがゲームをつなぐ
- 時間、待機、セーブ
- 進化した Scene ビュー
- 新しい外観
- ウィンドウのない Turian
- Guinevere 5.7 から 6.5 へ
- 皆さんの支援とともに
なぜ 3.0 なのか
Turian 3.0.0、関連 Issue:#35, #47, #62, #213
互換性を保ったままでは実現できない作業が2つありました。サーバービルドに Vulkan を含めずに済むよう、レンダラーをエンジンのコアから切り離す必要がありました。また、従来の色テーブルでは Material 3 に必要な表現ができないため、テーマを本格的なスタイルシート形式へ移す必要もありました。どちらも 2.0 のリリース時点ですでに進行中で、先送りすれば、後で移行が必要になる 2.x プロジェクトを増やすだけでした。
2.0 と同じく、互換性を損なう変更は1回のリリースにまとめ、移行ガイドも1つにまとめました。
| 変更 | 影響を受ける対象 | 更新手順 |
|---|---|---|
| Vulkan レンダラーを brick に分離 | レンダラーの型を直接使うコード。既存プロジェクトには brick を自動追加 | レンダラー |
| 設定とビルドプロファイルをプロジェクトアセットに登録 | すべてのプロジェクト。開く際に自動変換 | プロジェクトアセット |
| 内部メッシュ形式を glTF に変更し、OBJ インポートを任意の brick に分離 | .obj モデルを含むプロジェクト、書き出したゲーム、メッシュ関連ツール |
モデル |
カラーテーマを .pss スタイルシートに変更 |
独自テーマ、テーマの色を読み取るプラグイン | テーマ |
| Gaya の設定をクラスの属性から構成 | 設定ページやタブバーのウィジェットを持つプラグイン | Gaya |
| Guinevere 6 で描画とスタイル指定を変更 | Guinevere で直接描画するコード | Guinevere |
シーン、プレハブ、DataAsset の ID は維持されるため、コンテンツの変換は不要です。3.0.0 より後のリリースはすべて互換性を保っています。
物が落ちる:3D 物理
Turian 3.5.0・3.6.0、関連 Issue:#64, #48, #111
ほかのエンジンと比較したとき、Turian に最も欠けていたのは物理機能でした。その穴が今月埋まりました。Turian のほかの任意機能と同じく、brick としての提供です。
brick は2つあります。org.mass4.turian.physics はコンポーネント、設定、バックエンドの契約を定義し、単体ではシミュレーションしません。org.mass4.turian.physics.bepu がその契約に BepuPhysics v2 を接続します。Bepu は全体が C# で書かれた高速なマルチスレッド物理ライブラリです。ネイティブバイナリを必要とせず、.NET が動く環境で動作します。両方をインストールすれば、物が落ち始めます。フロントエンドは Bepu に直接依存しないため、将来バックエンドを変更してもシーンを修正する必要はありません。
Unity の物理機能を知っていれば、こちらもすぐに使えます。名前と挙動は意図的に Unity に合わせています。
- リジッドボディ:質量、減衰、重力スケール、キネマティックモード、補間、連続衝突検出、軸の固定、重心。力の適用には Unity と同じ
ForceModeを使います。 - コライダー:ボックス、球、カプセル、円柱、メッシュ、ハイトフィールド。1つのボディに複数のコライダーを付けると複合形状になり、ボディのないコライダーは静的になります。
- ジョイント:固定、ヒンジ、スライダー、球関節、距離、ばね。ヒンジとスライダーにはモーター、可動範囲の制限、ばねがあります。
- キャラクターコントローラー:
MoveとSimpleMoveを備え、段差や坂を上り、移動する足場にも乗れます。 - ホイールコライダー:レイキャスト式の車両向けに、サスペンション、タイヤの摩擦曲線、駆動・制動トルク、ステアリングを提供します。
- 物理マテリアル:DataAsset として摩擦、反発、Unity と同じ合成モードを設定できます。
- クエリ:レイキャスト、形状キャスト、重なり判定、貫通判定。月の前半にタグとレイヤーとともに追加された物理レイヤーで絞り込めます。
- コールバック:ハンドラーインターフェースを実装した任意のコンポーネントで、衝突とトリガーの Enter、Stay、Exit を受け取れます。
- ラグドール:
RagdollBuilder.FromSkeletonがスケルトンのボーンにカプセルと可動範囲を制限したジョイントを配置します。リグはアニメーション追従と物理による落下を切り替えられ、バインドポーズにも戻せます。

ベンチマーク用プロジェクトでは、毎秒200個の箱を1万個になるまで落とします。私のワークステーションでは、書き出したゲームはすべての箱がアクティブな状態でも約 80 fps を維持します。山が落ち着いてすべての箱がスリープすると、物理ステップの所要時間は1ミリ秒を大きく下回ります。これは1台のマシンでの測定値であり、性能の保証ではありません。ただ、プロファイリングによってエンジンのほかの部分でもメモリ割り当てを見つけて取り除けたため、月を通して数値は改善し続けました。

まだないものもあります。レイヤー衝突マトリクス専用のエディタ(現在の Inspector では32個のマスクをそのまま表示)と、異なるマシン間での決定性です。Bepu が決定性を持つのは同一マシン上だけです。
描画を減らし、速くする
Turian 2.1.0, 3.0.0・3.2.0、関連 Issue:#8, #59, #104
最も速く描けるものは、描かずに済ませたものです。
視錐台カリング
カメラが見られるのは、近クリップ面と遠クリップ面の間にある 視錐台 の内側だけです。今月までは、レンダラーはすべてのメッシュを GPU に送り、画面の外に出たものを GPU に捨てさせていました。現在は各サブメッシュがワールド空間の境界をキャッシュし、アクティブなカメラの視野外にあるものは、描画の記録やマテリアルの参照より前に除外します。回転・拡大縮小されたノード、プロシージャルモデル、透視投影と平行投影のカメラに対応しています。
約1,600個のサブメッシュからなる大きな通りのベンチマークシーンを、5台のカメラから測定しました。
| カメラ | カリング無効 | カリング有効 | 送信数 | 除外数 | 変化したピクセル数 |
|---|---|---|---|---|---|
| メイン | 2.43 ms | 2.12 ms | 1,322 | 269 | 0 |
| 全景 | 2.47 ms | 2.43 ms | 1,591 | 0 | 0 |
| 南 | 2.55 ms | 2.48 ms | 1,521 | 70 | 0 |
| 西 | 2.25 ms | 1.76 ms | 634 | 957 | 0 |
| 東 | 1.93 ms | 1.05 ms | 44 | 1,547 | 0 |
全景カメラには通り全体が見えるので、除外できるものはありません。東側のカメラには一角しか見えず、ほぼすべてを除外できるため、フレーム時間はほぼ半分になります。どの場合も、画像はピクセル単位で同一です。
GPU インスタンシング
描画呼び出しには、それ自体にコストがあります。どんなに小さなメッシュでも、呼び出しを記録する CPU 時間が必要です。レンダラーは、同じメッシュとマテリアルが連続する部分を1回のインスタンス描画にまとめるようになりました。同じ小物1万個を描くのに必要だった 8,791回の描画呼び出しが、同じ画像のまま1回になります。各コピーに独自の色と4つのカスタム値を持たせても、バッチは分割されません。
植生、群衆、破片のように1つのモデルを大量に持つシステム向けには、新しい Instanced Model コンポーネントがあります。単一の GPU バッファから全体を描画し、変更したインスタンスだけをアップロードし、集合全体を一括でカリングします。色付きキューブ1万個の CPU 時間は約 0.6 ms です。Scene ビューでインスタンスをクリックすれば、従来どおりそのノードを選択できます。

フレームを可視化する
これらの数値はプロファイラーなしで確認できます。Frame Statistics HUD は Scene ビューと Game ビューにフレーム時間、描画呼び出し数、インスタンス数、送信数、カリング数を重ねて表示します。ヘッドレスのスクリーンショットでも同じカウンターを報告するため、CI ジョブで性能の退行を検出できます。Studio 自体もオンデマンド描画になりました。変化がなければ再描画を止め、GPU をゲームに譲ります。
ワールド内の線、軌跡、文字
Turian 3.8.0、関連 Issue:#110
小さなコンポーネントを3つ追加しました。
LineRendererは点の列を通る線を描画します。平面状にも常にカメラを向く形にもでき、長さに沿った幅と色のカーブ、引き伸ばしまたは繰り返しの任意テクスチャに対応します。主な用途はレーザーやロープです。TrailRendererはノードが通った位置を記録し、時間とともに消える帯を描きます。剣の軌跡、タイヤ痕、彗星の尾などに使えます。WorldTextComponentは Guinevere が読み込める任意のフォントで、3D ワールドに文字を配置します。符号付き距離場を使って描くため、距離や角度が変わっても鮮明です。ダメージ数値や標識に向いています。
3つとも描画レイヤーに従い、透明ジオメトリと一緒にソートされ、Scene ビューとゲームの両方で動作します。デバッグにも便利で、物理テストシーンではクエリの線、軌跡、浮遊する衝突数値の描画に使っています。

デザイナーがゲームをつなぐ
Turian 2.2.0・3.7.0、関連 Issue:#91, #55
9月には、DataAsset をデザイナーの作業の中心にすると約束し、ScriptableObject アーキテクチャに関する Ryan Hipple の2017年の講演を紹介しました。10月には、そのパターン自体を実装しました。講演に登場するアセットと、それらを接続・デバッグする Studio のツールです。
イベント、変数、リスナーをアセットにする
新しい org.mass4.turian.ddd brick は、DataAsset-Driven Design(DataAsset 駆動設計)のためのものです。講演で紹介されたアセット群を Turian に導入します。
- イベント:データの有無を選べます。「プレイヤーが死亡」「コインを取得」「ドアが開いた」などです。
- 変数と定数:プレイヤーの体力を
FloatVariableアセットにすると、体力バー、音声、セーブシステムが同じ値を読み取り、変更通知を受け取れます。 - ランタイムセット:「今生きているすべての敵」のような集合を、敵自身が出現・死亡時に更新します。
- リスナーとレスポンス:イベントへの反応にスクリプトが不要になります。
- 状態遷移を持つ列挙型アセット:メニュー、プレイ中、ポーズ中などのゲーム状態を表します。
- 入力リーダー:入力アクションをイベントや変数へ変換します。
DataAssetReference<T> 型のコンポーネントフィールドには、通常の値も変数アセットも渡せます。そのためデザイナーは、コード変更を依頼せずに値をローカルにするか共有するかを決められます。UI brick のボタンはイベントを発行でき、Enabled と Visible の変数にも直接追従できます。
イベントの発行ではメモリ割り当てが発生せず、リスナー1つで約 4 ns、8つで約 12 ns です。ゲームロジックには十分軽い処理ですが、tick ごとや接触ごとのエンジンコールバックは、引き続き直接呼び出すのがよいと考えています。
ツールは併用する org.mass4.turian.ddd.studio brick が提供します。Assets パネルの Create → DDD から各種アセットを作れます。View → DataAsset Overview では、各アセットの発行元、リスナー、参照元を確認し、どこからも参照されていないものを探せます。Validate wires は接続先の欠落やデータ型の不一致を検出します。Play Mode ではエディタからイベントを発行し、変数の現在値を確認・変更できます。独自のデータ型には、DDD Type Generator がイベント、変数、セットのクラスを生成します。
まだないのは、リストと辞書のアセット、プレハブのインスタンスごとの非共有変数コピー、変数のセーブです。セーブには独自形式ではなく、セーブ用 brick を使う予定です。
タグとレイヤー
ノードに複数の文字列タグを付け、FindAllWithTag などのインデックス付きシーンクエリで検索できるようになりました。物理と描画には、それぞれ独立した32枠のレイヤーもあります。カメラとライトは描画レイヤーで対象を絞り込め、Scene ビューではレイヤーを非表示またはロックできます。レイヤー表は、安定した ID を持つ Tags and Layers 設定用 DataAsset に保存します。項目の名前や順番を変えても、それを使うシーンやプレハブは壊れません。既存コンテンツはファイルを書き換えず、タグを Untagged、レイヤーを Default として読み込みます。この表の今後の設計は別の記事にまとめました。アセットとしてのタグとレイヤーをご覧ください。
時間、待機、セーブ
Turian 2.1.0, 3.2.0・3.3.0、関連 Issue:#155, #88, #89
コルーチンなしで待つ
Unity のスクリプトはコルーチンで待機しますが、大規模プロジェクトでは多くの場合 UniTask に置き換えられます。Turian は C# 標準の async と await をそのまま使います。すべてのコンポーネントに Async プロパティがあり、そのライフタイムに結び付いた待機を提供します。
public class Door : Component
{
public bool IsBlocked { get; set; }
public async ValueTask OpenAsync()
{
Node.Position += Vector3.UnitY;
await Async.Seconds(2); // 時間スケール適用後のゲーム時間
await Async.Until(() => !IsBlocked);
Node.Position -= Vector3.UnitY;
}
}
次のフレーム、次の固定 tick、時間スケール適用・非適用の秒数、実時間、固定 tick の時間、条件が真または偽になるまでの待機を用意しています。継続処理は必ずゲームループに戻り、ワーカースレッドでは実行されません。コンポーネントが破棄されると、保留中の待機はキャンセルされ、存在しないオブジェクトで処理が走ることはありません。Studio のポーズはゲーム時間の待機を止めますが、実時間の待機は計測を続けます。保留中の待機はメモリを割り当てず、ゲームコードでの async void、Task.Delay、ValueTask の保存といった典型的な誤りはコンパイラーが指摘します。
信頼できる時計
TimeSettings アセットで、固定シミュレーションレートと、遅いフレームで追い付くために実行できる tick 数を設定できるようになりました。共通のシミュレーション時計が完了した tick を数え、ポーズと1ステップ実行を管理します。その上にある SimulationSession は、コマンドの受信と重複排除、tick の採番、名前付きの再現可能な乱数ストリームを持つ、ゲーム状態の正本となるワールドを提供します。Play Mode、ヘッドレスプレイヤー、書き出したゲームは同じ tick 境界を共有します。テストワールドは表示が 30、60、144 Hz のいずれでも、各 tick で同じ状態ハッシュを生成し、セーブから再開した後も一致します。ネットワーク機能自体はまだありませんが、これがその土台になります。
ゲームをセーブする
9月の RuntimeSave はシミュレーションのチェックポイントを作ります。新しい org.mass4.turian.save brick は、そのチェックポイントとゲーム独自のセーブデータを安全な場所へ保存するためのものです。
- バージョン付きスキーマ。 各セーブにゲームのスキーマバージョンを記録し、読み込み時に移行処理を順番に適用して1バージョンずつ更新します。保存済みファイルは書き換えません。
- 差し替え可能な構成。 標準は JSON で、任意のシリアライザー(MemoryPack、MessagePack、protobuf)やコンテナー形式を組み込めます。任意で使える AES-GCM 暗号化も含みます。
- データを守る書き込み。 まず一時ファイルに書き、完了してからスロットを置き換えます。前の世代はバックアップとして保持し、破損は黙って読み込まずに報告します。
- 上書き競合の検出。 書き込み時に置換対象のリビジョンを指定するため、2台のマシンや2つのプロセスが互いのデータを黙って上書きすることはありません。同じ契約をクラウドストレージにも適用でき、クラウドセーブの競合を再現するサンプルもあります。
レンダラーにもサードパーティーのシリアライザーにも依存せず、クライアント、専用サーバー、テストで動作します。

進化した Scene ビュー
Turian 2.1.0〜3.0.0、関連 Issue:#82, #68
エディタで過ごす時間の大半は Scene ビューでの作業です。そのため、10月の Studio 開発もここに集中しました。
ギズモ。 トランスフォームハンドルを作り直しました。太い矢印、塗りつぶしたスケール用ボックスと2軸ハンドル、カメラを向く回転円弧を備え、ホバー時に強調し、ドラッグ中は回転した角度を表示します。ワールド軸とローカル軸のどちらでも回転でき、角度スナップにも対応します。移動・回転・拡大縮小を同時に表示する統合ツールも追加しました。ハンドルはシーンのジオメトリより手前に表示されるので、壁に埋まったオブジェクトも移動できます。
方向。 隅に、軸のラベルが付いた小さなキューブ型の方向コントロールを配置しました。軸をクリックするとその方向を向き、中央をクリックすると構図を保ったまま透視投影と平行投影を切り替えます。基準グリッドはカメラ位置で正しくクリップされ、標準では XZ 平面に原点の軸を色付きで表示します。設定ページで間隔、強調表示、不透明度を調整できます。

ナビゲーション。 右ボタンを押したマウス視点操作では水平線を維持し、上下が逆さまになりません。矢印キーは変更可能な連続入力ショートカットでカメラを動かし、Shift で加速します。Scene パネルのツール、座標空間、スナップを小さなアイコンツールバーにまとめました。Cap FPS 設定を使えば、待機中の Studio がノート PC を熱くするのを抑えられます。
複数オブジェクトの編集。 Hierarchy と Assets パネルで Ctrl+クリック、Shift+クリックによる範囲選択、すべて選択が使え、Scene ビューでは矩形選択ができます。Inspector は選択対象に共通するコンポーネントを表示し、値が混在する場合は「—」で示します。共通フィールドを編集すると、選択した全オブジェクトが変わります。トランスフォームの1軸だけを変えた場合、ほかの軸はそれぞれの値を保ちます。一括削除、複製、親の変更、移動は、それぞれ1回の操作で元に戻せます。

そのほか。 コミットログでは「気が狂いそうだった1001個の不具合修正」とまとめましたが、だいたいそのとおりです。特に気付きやすい変更は次のとおりです。
- 一時シーン。 File → New Scene(Ctrl+N)で試作用のシーンを開きます。保存するまでアセットは作りません。
- Assets パネルの刷新。
- 読み込みカードで、プロジェクトを開く際に Studio がインポート・コンパイルしている内容を表示します。
- 再オープンの高速化。 変更がなければインポート済みファイルを再利用し、Build & Run は変更されたアセットだけをコピーします。
新しい外観
Turian 3.0.0、関連 Issue:#212, #213, #214, #215, #217
Studio の標準の外観は、Guinevere が描画する Google の現行デザインシステム Material 3 になりました。
外観は4つの独立した選択肢に分かれています。ルック(各コントロールの形)、カラーテーマ、アイコンセット、フォントです。テーマは Guinevere 版 CSS ともいえる .pss スタイルシートで、編集中にライブリロードされます。アイコンセットには Mono と Color があります。
ルックとテーマは brick なので、誰でも作って共有できます。turian-cli はコマンドラインからテーマを brick にパッケージ化できます。Bricks パネルは Gaya に移り、Studio 自体の brick とプロジェクトの brick を別々のスコープで管理します。最初の追加ルック2つは、少し懐かしい Windows XP と Windows 9x です。ほかの brick と同じようにインストールできます。
ゲーム内 UI も恩恵を受けます。Vulkan 使用時は GPU で描画するようになりました。
ウィンドウのない Turian
Turian 3.0.0〜3.8.0、関連 Issue:#35, #62, #292, #313, #344
ゲームのビルドに、必ず画面があるとは限りません。専用サーバーや CI 上のヘッドレスシミュレーションには GPU は不要で、そのための描画機能を同梱する必要もないはずです。
- ビルドプロファイル。 プロジェクトに複数のビルドプロファイルを保持できます。それぞれがプラットフォーム、クライアントまたはサーバーの役割、構成、独自の定義シンボルと設定を持ち、Build Profiles ウィンドウで編集します。
Assets/Project.dataassetに、プロジェクト設定と最後に保存したエンジンのバージョンとともに登録します。 - ヘッドレスサーバー。 レンダラーは brick なので、サーバープロファイルからは単に除外できます。ヘッドレスプレイヤーは同じシーンとシミュレーション tick を実行し、Ctrl+C で正常終了します。
- NativeAOT サーバー。 デスクトップ向けサーバープロファイルを事前コンパイルし、単一のネイティブ実行ファイルにできます。.NET ランタイムのインストールも JIT のウォームアップも不要です。以前はリフレクションに頼っていた起動コードをエディタが生成し、必要な要素が欠けていれば実行時ではなく書き出し時に明確なエラーになります。テスト用サーバーはトリミング警告なしで書き出し、実行、正常終了まで確認できています。
- 小さな brick へ。 エンジンはコアへの集約を続けています。カメラ、ゲーム内 UI、OBJ インポート、セーブ、Windows のルックは独立した brick リポジトリに移りました。今月はローカライゼーションもコアとレンダラーから専用 brick に分離しました。Bepu バックエンドのように、brick は必要な NuGet パッケージも宣言でき、Git コミットやアーカイブのチェックサムで固定したソースにも依存できます。

Guinevere 5.7 から 6.5 へ
Studio を描画しているのは Guinevere です。そのため、ここまでの内容のかなりの部分は Guinevere 側の開発でもあります。今月は 5.7 から 6.5 までリリースしました。互換性を損なう変更があったのは、Turian 3.0 の新しい外観の基盤になった 6.0 だけです。
- スタイル。 Excalibur コントロールの標準は Material 3 になり、従来の外観も
ExcaliburStyles.Classicとして利用できます。スタイルシートは独立したMASS4.Guinevere.Stylingパッケージの.pssファイルになりました。値の式、テーマ色関数、システムの配色とアクセントカラー、文字の影とグロー、ビットマップ背景と9スライス背景に対応します。 - GPU 描画。 Silk.NET、OpenTK、Raylib の統合は Skia を使って GPU で描画し、CPU をフォールバックとして保持します。どの統合も標準でオンデマンド描画を行います。
- アニメーション。 キーで識別するスプリングとトゥイーン、プロパティのトランジション、アニメーション付きの状態変更。
- 描画エフェクト。 順序付きのエフェクトスタックを、文字、図形、画像を含むパネル全体に適用できます。13種類の組み込みフィルターは、ぼかし、グロー、影、色調整、ピクセル化、色分離、シャープ化をカバーし、C# または
.pssで設定できます。 - コードエディタ。 新しい TextEditor パッケージは、表示を仮想化したソースコード・シェーダーエディタです。複数キャレット、矩形選択、折りたたみ、検索・置換、補完、ホバー時のドキュメント表示、バックグラウンド診断を備え、10万行のファイルも通常どおり扱えます。
- テキスト。 スタイル付きの範囲、リンク、インライン画像を持つリッチテキスト、構文強調付きコードブロックに対応したストリーミング Markdown コントロール、組版設定(間隔、タブ位置、両端揃え、カーニング)、任意のリガチャ・結合文字用シェーピングを提供します。テキストレイアウトはキャッシュし、計測と描画で共有するようになりました。
- グラフ。 新しい
MASS4.Guinevere.Graphsはノードグラフエディタです。パン・ズーム可能なキャンバス上のノード、ポート、リンクに加え、矩形選択、折りたためるグループ、コピー・貼り付け、元に戻す、ミニマップ、.pssによるスタイル設定を備えます。すべてキーボードで操作でき、Linux では新しいデスクトップアクセシビリティブリッジを通じてスクリーンリーダーに情報を提供します。 - ゲーム、ゲームパッド、タッチ。 ゲームパッドでのフォーカス移動、意味に基づくコントローラーアクション、任意のジェスチャーを備えたマルチタッチ、スマートフォン向けセーフエリア対応ビューポート、ゲーム内 UI 用の HUD プリミティブ。
- 細かな改善。 部品を差し替えられるカラーピッカー、検索可能な複数選択ドロップダウン、フラグに対応した列挙型エディタ、ドッキング先を示すタブを追加しました。

皆さんの支援とともに
ここに挙げていない修正、調整、改善も数多くあります。全一覧は変更履歴をご覧ください。ドキュメントでは、brick、描画、ギズモ、テーマを解説しています。不具合があれば GitHub で教えてください。次のリリースの開発費を支援してくださる方は、Patreon または Ko-fi をご利用いただけます。
#release#engine#studio#physics#dotnet