サバイバルキッズからのグラフィックスとレンダリングのヒント

STEVEN CANNAVAN AND DANIEL REIDLER / UNITYSurvival Kids
Aug 20, 2025|8 分
サバイバルキッズのゲームプレイ
このウェブページは、お客様の便宜のために機械翻訳されたものです。翻訳されたコンテンツの正確性や信頼性は保証いたしかねます。翻訳されたコンテンツの正確性について疑問をお持ちの場合は、ウェブページの公式な英語版をご覧ください。

この夏、UnityはKONAMIと提携して、エンドツーエンドで社内開発された最初のゲーム、協力型ファミリーゲーム「サバイバルキッズ」のアップデートをリリースしました。このゲームは、最大20人の小さな内部チームによって構築されたため、チームは限られたリソースでプロジェクトの範囲とリリースのタイムラインを維持するための革新的な方法を見つけなければなりませんでした。この記事では、ゲームのビジュアルフレームとレンダリングをどのように作成したかを掘り下げます。

ビジュアルアイデンティティの定義

私たちは視覚的に興味深いものを達成したいと考えていました。私たちの目標は非常に芸術的でしたが、最初にどのようなデバイスの能力で作業するか分からなかったので、パフォーマンスの面で非常に安価にしたいとも考えていました。

プロジェクトの最初の部分は、視覚的に探求することだけでした。私たちは、アートがどのようになるかを示すために使用していたアートジオラマを持っていました。その一部は、カスタマイズされた影を含む非常にスタイライズされたライティングセットアップです。

私たちは、幅広いデバイスでのパフォーマンスに優れた実績があるため、ユニバーサルレンダーパイプライン(URP)を選びました。また、ゲームのビジュアル目標を達成するために必要な新機能を作成するのも比較的簡単です。レンダリングされたフレームは、ゲームが主に1つの光源、太陽しか持っていないため、フォワードモードのバニラURPに非常に近いです。カスタムシャドウ、アンビエントオクルージョン、その他のカスタムレンダリング機能など、いくつかの修正がありますが、全体的には画面上のバニラURPです。

サバイバルキッズのゲームプレイ
サバイバルキッズのゲームプレイ

最大の追加は、アートディレクションの非常に特定の外観をサポートするためのシェーダーへのものでした。照明の計算方法を変更する必要がありました。カスタムシェーダーを作成することは特に新しいことではありませんが、誰でも貢献できるように独自のカスタムShader Graphターゲットを作成しました。AssemblyDefinitionReferenceを使用することで、完全にカスタムのURPバージョンを持たずに、プロジェクト固有のShader Graphターゲットを追加できました。これにより、私たちはローカルのShader GraphターゲットだけでバニラURPに固執でき、プロジェクトに非常にうまく機能しました。

ライティングとグローバルイルミネーション

私たちの目標の1つは、ダイナミックライティングを持つことでした。ライティングの色、強度などを変更できるオプションが欲しかったのです。そのため、ライトマップを使用して照明情報を簡単にベイクすることができず、バウンスライティング/グローバルイルミネーションでベイクすることで得られる照明の詳細が欠けてしまうことになります。通常、ダイナミックライティングアプローチはより高価であるため、高い視覚品質と良好なパフォーマンスのバランスを取るための異なる方法を考える必要がありました。これにより、最初にLightProbesを使用し、オブジェクトを地面に固定するためにAmbient Occlusion (AO)により多く依存することになりました。

サバイバルキッズ環境における照明とグローバルイルミネーション情報
照明とグローバルイルミネーション情報

グローバルイルミネーションがこのプロジェクトにとって非常に重要であることが分かっていたので、最初にLightProbesをランタイムで更新するカスタムソリューションを実装しました。しかし、Unity 6に移行したとき、チームは視覚的品質が比較可能なパフォーマンス影響を持ちながら、私たちが組み立てたシステムよりもかなり良かったため、Adaptive Probe Volumes (APVs)に切り替えたいと本当に望んでいました。良いものから本当に良い高品質でパフォーマンスの良いものにアップグレードするオプションがあるときは、ただ切り替えます。

海洋

海洋はUnity URPデモプロジェクト「ボートアタック」に大きく基づいていましたが、よりスタイライズされた外観を持っています。私たちが本当にやりたかったことの一つは、島や水中の他の要素からの波が出ることでした。これは通常、距離によって海岸線を計算するために深度バッファを使用して実装されますが、実際には海岸線はなく、Whurtle島があります。

波は小さな島の環境の海岸線から設定された距離で海水中に発生します。
符号付き距離フィールド (SDF) は、海岸線から設定された距離で波を生成します。

Whurtle島では急激な落下があり、効果のための深度の減衰が不十分であり、特に水中に沈んでいる地形を考慮するとそうなります。私たちが考えた最良のアイデアは、符号付き距離フィールド、つまりSDFを使用することでした。基本的には、オブジェクトの符号付き距離をエンコードするテクスチャであり、私たちの場合は海岸線です。この方法で、海岸線から特定の距離で波を開始し、正弦波といくつかの歪みテクスチャを使用して興味深い外観を与えることができます。

最終的に、4つの設定された水位に基づいて海岸線の符号付き距離をベイクするエディターツールを持っていました。その後、海岸線が実際にどこにあったかの粗い近似のために、それらの間でブレンドと線形補間を行いました。ほとんどのレベルでは水位がプレイヤーの進行状況に応じて変化します。私たちは、海洋波の高さを調整することから泡、波、コースティクスを追加することまで、いくつかの異なる効果のためにこの事前ベイクされたSDF情報に依存しました。


フレームの内訳
レンダリングされたフレームの高レベルの内訳
レンダリングされたフレームの高レベルの内訳で、赤でマークされたパスはカスタマイズされています
視覚的インタラクション

視覚的インタラクションのために、プレイヤーや運搬可能なオブジェクト、ツールなど、位置を追跡する必要があるものの周りに、上からのビューでカプセルがレンダリングされ、RenderTextureに入れられます。テクスチャはワールド空間に基づいており、プレイヤーのカメラが移動するにつれてスライディングウィンドウがあります。

カプセルの中心からオフセット(赤、青)を生成し、ワールドスペースの高さ情報(緑)も生成します。アルファチャンネルには、強度のためのフォールオフ値を格納します。それは、植生の曲がり、水面のアニメーションリップル、または地形を少し暗くして非常にソフトな影効果を作成するための異なるシェーダーによって使用されます。


シェーダーは、プレイヤーやオブジェクトの周りのRenderTexture「カプセル」に適用され、影や水の中の波紋など、世界により根付いているように見せる効果を作成します。
シェーダーは、各プレイヤーや運搬可能なオブジェクトの周りのRenderTexture「カプセル」に適用され、影や水の中の波紋など、世界により根付いているように見せる効果を作成します。
深度とディザのプリパス

パフォーマンスの最適化のために、オブジェクトを通常通りレンダリングする前に深度バッファを埋める深度プリパスを使用し、早期の深度テスト拒否によってオブジェクトのレンダリングコストを削減しました。

ジオメトリの背後を見るために、SMAAパスでぼかしに使用されるステンシルとディザパターンでの深度のプリフィル
ジオメトリの背後を見るために、SMAAパスでぼかしに使用されるステンシルとディザパターンでの深度のプリフィル

ディザされたオブジェクトは、状態やどのプレイヤーがそれを見ているかによって異なる方法でレンダリングする必要があるため、カスタムパスで別々に処理しました。それらは、レンダラーの不透明レイヤーマスクから除外された異なるGameObjectレイヤーにあり、自動的にレンダリングされないため、カスタムパスでレンダリングする必要があります。オブジェクトの個別の値を設定するためにMaterialPropertyBlocksを使用し、後でそれらのセクションをぼかすためにディザされたオブジェクトをマークするためにステンシルを適用しました。ただし、これによりSRPバッチ処理が壊れるため、その使用を制限する必要がありました。必要に応じてのみMaterialPropertyBlocksを適用し、完了したらそれらを削除してオブジェクトをバッチ可能な状態に戻すことに決めました。

最終的に、特定のレイヤーを深度バッファにレンダリングする方法を処理する全体のパスがあります。次に、深度バッファにステンシルを適用して、フェードアウトしているオブジェクトの一部であるピクセルをマークし、その後、アンチエイリアシングを行うときにそれが使用されます。

グラデーションシャドウ

私たちのアートスタイルの一部は、影の方向に沿ったグラデーションのあるカラフルな影を持つことでした。これを実現するために、ワールド空間でシャドウマップをサンプリングし、XZ平面で先を見越してシャドウブレンド値を決定するカスタムスクリーンスペーステクスチャを生成しました。これはソフトシャドウで使用されるPCFフィルターに似ていますが、一方向のみです。これは画面の約4分の1のサイズのダウンサイジングされたテクスチャにレンダリングされ、3つの色の間で影の色をブレンドしました。

低解像度のスクリーンスペースパスで影のエッジグラデーションカラーを生成し、光の方向にグラデーションを作成します。その後、バイリニアサンプリングに依存します。
低解像度のスクリーンスペースパスで影のエッジグラデーションカラーを生成し、光の方向にグラデーションを作成します。その後、バイリニアサンプリングに依存します。
MSVAO(マルチスケールボリュメトリックアンビエントオクルージョン)

残念ながら、URPに付属のSSAOは私たちのニーズにはあまり適していませんでした。モバイルフレンドリーな実装ですが、私たちが目指していた見た目のためには、半径値をかなり高く設定する必要があり、フレームバジェットのかなりの部分を消費しました(約4ms)。代わりに、古いPostProcessing Stack v2パッケージからMSVAOの実装を再利用し、より効率的にし、影の色を統合するためにいくつかの小さな変更を加えました。

ターゲットプラットフォームでのパフォーマンスを向上させるために小さな調整を加えたPostProcessing Stack v2パッケージからのMSVAOのカスタマイズ版の島のシーンの透視。
ターゲットプラットフォームでのパフォーマンスを向上させるために小さな調整を加えたPostProcessing Stack v2パッケージからのMSVAOのカスタマイズ版。
シーンの描画

サバイバルキッズは、URPで期待される標準のレンダリングパス(不透明、スカイボックス、透明)を持っていますが、不透明パスの直後にディザリングされたオブジェクトを処理するための追加のパスもあります。ここでは、ジオメトリが不透明パスでレンダリングされないため、実際にディザリングされたジオメトリをレンダリングします。このパスでは、深度バッファを事前に埋めた場所のみをレンダリングすることを確認するために、深度等しいテストも行います。

ディザリングされたオブジェクトのためのジオメトリの描画(深度等しいテスト)。この状態ではアンビエントオクルージョンは無効です。
ディザリングされたオブジェクトのためのジオメトリの描画(深度等しいテスト)。この状態ではアンビエントオクルージョンは無効です。

ディザリングされたオブジェクトについては、MSVAOが深度バッファの「穴」をオクルージョンとして扱うため、アンビエントオクルージョンを無効にする必要があります。

ディザリングにSMAA + ブラーを使用した視覚効果を示すゲーム画像。
SMAA + ブラーをディザに適用

シーンがレンダリングされた後、アンチエイリアシングを適用します。残念ながら、ディザされた領域はアルゴリズム(SMAA)を混乱させ、視覚的なアーティファクトを引き起こします。これを避けるために、これらの領域を別々に処理する必要があります。ディザされた領域(ステンシルによって決定される)はぼかされ、これらの領域にアルファブレンド効果を生成し、その後、ディザされていない領域でSMAAが処理されます。特定の状況ではこれをスキップしますが、最終的にはポストプロセスの準備が整ったクリーンな画像が得られます。

ポストプロセスとUI

私たちは、トーンマッピング、ブルーム、色補正を少し使用して、ポストプロセスエフェクトをできるだけ安く保ちました。

ある時点で、UIの背後にあるゲームを柔らかくするためにURPのブラーをポストプロセスで使用しましたが、後にそれをより安価なカワセブラーのレンダーフィーチャーに置き換えました。私たちのUIシステムはUGUIに基づいており、フェードのために少しカスタムレンダリングを行っています。

サバイバルキッズのUI
サバイバルキッズのUI

最初にUIを設定した方法では、メニューをフェードイン・アウトしていましたが、このアプローチはUIのアルファ処理の方法によりいくつかの問題を引き起こしました。最初は、カメラを介してUIを別のテクスチャにレンダリングし、それを正しくブリットしてUIをメイン画像にフェードさせることを始めましたが、これを全体の追加カメラを使用するのではなく、レンダーフィーチャーを使用して達成できるように変更しました。

この投稿は、サバイバルキッズのターゲットレートを達成するためにスタイライズされたパフォーマンスのグラフィックスとレンダリングを設定する方法を垣間見るものです。ゲームに関するさらなる内部の投稿については、Unityブログをフォローしてください。マルチプレイヤーネットワークに関する2部構成の深掘りや、チームのレベル地形とワークフローについての投稿もあります。また、私たちのリソースページでより技術的な開発者ストーリーをチェックしてください。