Joël van der Werf
記事一覧

街灯は一つのもの:シーンヒエラルキーと実行時UI

親子関係のあるエンティティと本物のUIシステムを、2つのシンプルな目標に沿って計画し、2日で実装しました。小さく保つための判断を紹介します。

Hydroのシーンには2つのものが欠けていました。エンティティが子を持てないこと。街灯の柱、ライト、影、炎は、互いに関係のない4つのエンティティでした。そして、ゲームのメニューはUIのふりをしたスプライトの列でした。両方を1つの計画にまとめ、目標は2つだけ、それ以外は対象外にしました。

  1. ヒエラルキー:エディタで街灯の柱を動かすと、ライト、影、炎がついてくる。プレハブとして保存すれば、どのインスタンスも子を持ってくる。
  2. UI:インベントリ、バトルのコマンド、長老のセリフが本物のUIになる。テキスト、ナインスライスのパネル、キーボードフォーカスを持ち、ウィンドウをリサイズしても位置が保たれる。

ヒエラルキーの判断

  • 親へのリンクだけ。各エンティティは親のIDだけを持ちます。子は導き出され、シーンのエンティティの順序がそのままツリーの深さ優先の順序です。親・最初の子・次の兄弟を持つ方式は、常に一致していなければならない3つのリンクになります。
  • ダーティフラグなし。ワールド変換は毎フレーム、すべてのエンティティについて1回の線形パスで計算し直します。スクリプトは多くの場所で位置を直接書き換えるので、ダーティフラグが確実に立つことはありません。プロファイラーが求めたときだけ追加します。
  • 派生データは専用のコンポーネントに。ワールド変換は、元のコンポーネントと一緒に追加・削除される別のコンポーネントにあります。計算するパスがイテレーション中にレジストリを変えることはありません。

UIの判断

  • Unityと同じモデル。アンカー付きのRectTransform、Y軸は上向き、原点は左下。UnityのUIを作ったことがある人なら馴染みがあり、よく理解されている方式です。
  • まずはビットマップフォント。BMFontファイルを既存の2Dレンダラーで矩形として描くので、新しいシェーダーは不要です。任意のTTFから32pxで作ったビットマップフォントなら、等倍で十分滑らかです。距離場(SDF)テキストは後から追加できます。
  • 入力のキャプチャはフォーカスとは別。ゲームプレイの入力を止める表示中のキャンバスが入力をキャプチャし、フォーカスはキーボード操作の行き先を示すだけです。フォーカスを合図にすると、ボタンのないダイアログボックスで破綻します。
  • 1つの設定で2つのスタイル。テストベッドは1920×1080基準の滑らかなフォントですが、同じスケールモードの設定で480×270の整数倍スケールのピクセルUIにもできます。
UIのキャンバス、パネル、タブが入れ子になったOxygenのヒエラルキー
ヒエラルキーでの結果:プロンプト、フィールドHUD、フィールドメニューのキャンバスと、その子として入れ子になったパネル、タブ、テキスト。

デモではなく、作り直しで検証

計画の検証方法は、既存のメニューを本物のUIで作り直し、スプライトで作った偽物を削除することでした。街灯と神社の灯籠は、子を持つプレハブになりました。2日間で、すべてのステップをエディタで確認しながら実装しました。

学び:目標を2文で書き、それに役立たないものはすべて削る。だからこそ計画は小さいままでした。

前の記事:Joltで歩けるジオラマ:カプセル、スロープ、ゲームプレイ用の形状次の記事:エディタから.exeへ:初めてのスタンドアロンビルド

お仕事のご相談はお気軽にどうぞ

東京在住です。Unity・C++・ゲームエンジン関連のポジション、C#・.NETのソフトウェア開発のポジション、そしてAIエージェントを活用した開発体制づくりに関心があります。英語・オランダ語・日本語(勉強中)で対応できます。