ゲームプロジェクト · USC Games · That Game Jam · 5 人チーム

この身、風のごとく(Light as Wind)

海を越え、遠い空を目指す、夢のようなピクセルアートの横スクロールゲームです。私はチームのデザイナー兼エンジニアとして、全 10 レベルのうち 3 つのレベルデザインを手がけ、ゲームを支える物理・シェーダー・破壊表現のシステムをいくつか構築しました。

Level 03 のゲームプレイ:チョウチンアンコウから身を隠す場面。ゲーム内の生き物はすべて、スケルタルリグを使わずプロシージャルにアニメーションしています。

担当

デザイナー · エンジニア

Level 04、06、10 のレベルデザイン(シーン、ルート、メカニクス)を手がけました。ゲーム全体では、インタラクションメカニクスの設計、ゲームプレイのロジックとエフェクトの実装、QA とバグ修正を行いました。

エンジニアリング面では、動くものの手触りに注力しました。風にさらわれる紙、メカジキの泳ぎ、カニのツタ渡り、そして壊れて砕けるプロップなどです。また、ゲーム内の「空気の壁」のシェーダーも書きました。

このプロジェクトには厳格なルールがあります。後から Unity 以外へ移行できるよう、各システムのロジックはエンジンの型を使わない純粋な C# で書くこと。そして、すべての変更はスクリーンショットより先に、プローブ、ログ、ルート検証ボットといったデータで確認することです。

エンジン
Unity 6 / C# / HLSL
チーム
学生 5 人、USC Games
プラットフォーム
Windows(itch.io)
ステータス
第 1 部 配信中

プロジェクトの土台

レンダリング & プロシージャルアニメーション

この身、風のごとくは、2 つの技術的な土台の上に成り立っています。動く 3D の透視投影カメラの中でも崩れないピクセルアートと、スケルタルリグを 1 つも使わず、すべてコードで動かす生き物のアニメーションです。私が構築したシステムは、この土台の上に作られています。

01

独自のレンダーパイプライン

ゲームは段階的に URP から独自のパイプラインへ移行しました。土台は純粋な C# で書かれたエンジン非依存のフレームグラフで、Unity はバックエンドの 1 つにすぎません。各段階は参照フレームとテクセル単位で照合して検証しました。シェーダーバリアントは 603 から 36 に減り、1 フレーム全体の GPU コストは約 0.4–0.5 ms です。

02

透視投影の中のピクセルアート

各オブジェクトは低解像度のテクセルグリッドに剛体的にスナップし、残ったサブピクセルのずれを G-buffer に格納して画面解像度で解決します。そのため、カメラが滑らかに動いてもシルエットがちらつくことはありません。やわらかな間接光は、ワールドに固定したプローブを用いた 2.5D の Radiance Cascades によるもので、コストは約 0.3 ms です。

03

プロシージャルアニメーション

スケルタルリグは一切使っていません。進行波で動く魚の脊椎、XPBD と Verlet のチェーン、コンピュートシェーダーでシミュレーションするクラゲ、そして 1 回のドローコールで描かれる 5,000 匹を超える Boids の魚群です。

レベルデザイン

デザインしたレベル

システム

物理、シェーダー & 破壊表現

05 のハイライト

01 · シミュレーション

風に舞う紙

紙は 1 枚ずつ、風下側の辺を蝶番にして回転しながら持ち上がり、34° までめくれてから離れます。空中では速度が指数的な追従で目標の風速へ近づき、落ち葉のような揺れ(±0.3 m、周期 2.1 s)が傾きと振れを連動させるので、紙は曲がるたびにその方向へ身を傾けます。

風が届く前は、減衰の弱いバネで角がはためきます。壁の拘束によってポスターは壁の手前にとどまり、壁面に沿って滑り落ちるので、壁を突き抜けることはありません。

突風 1 回あたり
15–17 枚、すべて 0.22–2.33 s で画面外へ
壁へのめり込み
0.7–2.6 m → 0
モデルは純粋な C#(System.Numerics、エンジンの型は不使用)で、Unity は描画だけを担当します。

02 · シェーダー · Worley ノイズ

空気の壁:夢の海の皮膜

見えない壁は、バグではなく夢の一部として感じられる必要がありました。壁にはゆっくり漂う Voronoi / Worley の網目が浮かびます。線はセル境界までの正確な距離で描くため、どの角度でも 1 ピクセル幅のまま途切れません。境界ごとにプランクトンの色のいずれかを割り当て、ところどころで金色の粒がきらめきます。

ぶつかると一対のリングが広がって網目を押しのけ、衝突点から泡が漂い出します。幕は近づいたときにだけ現れます(1.8 m から、0.95 m で最大)。明るさはディザリングを使わないくっきりした段階で表現し、プロジェクト独自のヘッダー上に移植性のある HLSL で実装しました。

03 · ゲームフィール

メカジキの泳ぎ

メカジキは、マグロ型の脊椎の波動、本物の魚のように頭が尾と逆向きに振れる質量加重の反動、そしてストローハル数で決まる尾びれの振動数で泳ぎます。

私は操作感を調整しました。実際に壁に触れるまではブレーキをかけない(距離は進行方向に沿って吻の先端から測定)、天井や草の斜面に沿って速度を落とさずに滑る、跳躍の合間に潜る、上下の方向転換を素早くする、といった点です。

04 · シミュレーション

カニのツタ渡り

カニは振り子で、ツタはそのハサミに追従するだけです。2.5D のゲームでは純粋な 3D 距離だと掴み損ねが続いたため、掴み判定は画面の平面上で測っています。プレイヤーは振りと同じ位相でしか漕げず、エネルギーの上限(最大 72°)によって、長いツタでもカニが画面外へ放り出されないようにしています。

各ツタは 18 ノードの Verlet ロープで、拘束の反復 8 回、水の抵抗、ゆっくりした揺れを備えています。ハサミより下のノードはカニの甲羅の外へ押し出されるので、めり込むことはありません。

平均フレーム時間(Level 7/8/9)
6.4/7.7/8.5 → 1.7/2.6/2.7 ms
16.7 ms を超えたフレーム数
89/165/166 → 4/0/0

05 · 破壊表現

レベルを切り分ける

このゲームにはインポートしたメッシュが一切ないため、破壊とは生成されたジオメトリを切ることを意味します。Level 06 の崩れるトンネルでは、洞窟の天井が自らを砕きます。頂点を溶接し、union-find で閉じた岩ごとにまとめ、長い岩はランダムな平面でクリップし(Sutherland–Hodgman、すべての属性を補間)、各切断面をファンで塞ぐことで、すべての破片が閉じたソリッドのまま保たれます。

切断処理はフレームあたり 4 ms の予算を持つコルーチンとして動き、プレイヤーがまだ 60 m 手前にいるうちに始まります。610 個の岩が 140–220 フレームかけて 169 個の破片になります。小さなプロップは、隣り合う破片同士で継ぎ目を共有するあらかじめ切り分けたピースで壊れ、破片は物理エンジンをまったく通さないため、コストはフレームあたり約 0.013 ms です。

トンネル崩落
岩 610 個 → 破片 169 個
プロップ破壊時の最悪フレーム
14.6 → 3.3 ms