【Unity】ゲームの最適化テクニック総まとめ!重いゲームをサクサク動くようにしよう

Unityの最適化手法総まとめゲーム開発

今回はUnityの最適化に関する話題で、今までに私が得た最適化の知識を総まとめしておこうという内容の記事です。

私は(執筆時点で)3Dゲームを15作品以上作った経験があるのですが、3Dゲームとなるとどうしても処理が重くなりがちで毎回最適化に関する悩みを抱えてきました。特に私の初期のオープンワールドゲーム等では

ゲームが重すぎてまともに遊べない!

といった苦情をたびたび頂いたほどで、3Dゲームを作るからにはきちんとゲームを最適化しないとダメだなということを嫌というほど痛感したものです。しかし、とりわけ初心者の頃は一体どうすればゲームが軽くなるのか全く分からず苦労しました。このような経験から最適化は重要であるにも関わらず「やり方がよく分からない」という理由で放置されがちであり、失敗の原因になりやすいことを実感しました。

そこでこの記事では皆さんが私と同じような苦労をしなくて済むように、過去の最適化の記事でとりあげた内容を復習しつつ、具体的な最適化のやり方を初心者の方でも分かるように説明していきます。ぜひ参考になさってください。

そもそも「最適化」とは?

では具体的な内容に入る前に、「そもそも最適化って何?」という方もいらっしゃるかもしれないのでその点について簡単にお話しておきます。

ゲーム制作における最適化とは、一言でいえば

無駄な処理を減らしてゲームがサクサク動くようにする

ことです。

ゲームを作っていると制作サイドの都合でPCに無駄な処理をさせる結果になってしまうことが非常によくある(例えば、作るのが簡単だがPCへの負荷が高い処理になることがある)のですが、ひと手間かけてそういった処理を改善していくのが最適化だといえるでしょう。

最適化のお供「プロファイラー」

それでUnityで最適化を行うにあたって重要なのがゲームの処理負荷を視覚化することです。最適化を行うからには

  • どの処理で負荷が掛かっているのか?
  • どのタイミングで負荷が掛かっているのか?

といったことが分からないと原因をつぶすことは困難ですよね。そこでUnityには「プロファイラー」という負荷をモニタリングするための機能(※下図)があるのでそれをうまく活用しましょう。

プロファイラーの画面の例

プロファイラーウィンドウの出し方

もしプロファイラーウィンドウが出ていない場合は、メニューバーの「ウィンドウ」→「分析」→「プロファイラー」からプロファイラーウィンドウを開くことができます。適当な位置にドッキングして常駐させておくとすぐにグラフを確認できて便利です。

プロファイラーの基本的な使い方

プロファイラーには様々なグラフが表示されますが、とりあえず初心者の方は一番上の「CPU Usage」のグラフの見方を覚えてください。

プロファイラーのCPU Usage

このグラフは横軸が時間(単位はフレーム)・縦軸が処理時間(単位はミリ秒)になっています。処理時間は短いほど良いので、基本的にグラフの位置が低いほど良い結果が出ていると思っていただければ差し支えないでしょう。

あとグラフを見てみると色が分かれていると思うのですが、これはそれぞれの色ごとに描画処理とか、物理演算といった処理内容を表しています。色分けの一例を挙げると

  • 描画処理:緑
  • スクリプト;青
  • アニメーション:水色
  • 物理演算:オレンジ

といった感じです。このグラフを見れば、どのタイミングでどのカテゴリの処理が重いのかが一目でわかるのでとても便利です。

プロファイラーによる分析はとても奥が深いのでここではほんの少ししか説明できませんが、慣れてくると表示されるグラフから色々なことが分かるようになるので最適化すべき部分の特定には必要不可欠です。興味のある方はぜひググって頂き、さらに詳しい使い方を学んでみてください。

Unityの主な最適化のカテゴリは3つ

さて基本的な部分についてご理解頂いたところで、Unityにおける最適化について具体的にご説明していこうと思います。Unityで主に行える最適化は大きく分けると次の3つのカテゴリがあります。

  1. グラフィックの最適化
  2. 物理演算の最適化
  3. C#スクリプトの最適化

以下でそれぞれについて詳しく見ていきましょう。

グラフィックの最適化

まずはグラフィックの最適化についてです。個人的な経験から言うと3Dゲームの場合はグラフィック関係の処理が最も重くなりやすいので、特に重点的に最適化を行う必要があると思います。

グラフィックの最適化にあたって特に重要な手法は次の通りです。

  1. URPを使用する
  2. カメラの設定を見直す
  3. メッシュを結合する
  4. マテリアルを統一する
  5. テクスチャサイズを見直す
  6. ライトを使い分ける
  7. Terrainの設定を見直す
  8. ポストプロセスを使いすぎない
  9. LODグループを上手く使う
  10. シェーダーを軽量なものに変更する
  11. オクルージョンカリングを使う

URPを使用する

まず一つ目の手法は、デフォルトのテンプレートではなくURPを使うことです。デフォルトのテンプレート(=ビルトインレンダリングパイプライン)は旧式のグラフィック描画方式を採用していて遅いので、プロジェクトの作成時にURPを選択することでグラフィック描画を高速化することができます。

デフォルトテンプレートとURPの具体的な違いについては以下の記事でご紹介していますので、併せてご覧いただければと思います。

【Unity】URP・HDRP・ビルトインを徹底比較!一体どれを使えば良いのか?
皆さんはUnityで新しいゲームを作り始めるときに「一体どのレンダリングパイプラインを使えばいいんだろう?」と迷ったことはありませんか。個人的にこれはUnityならではの悩みどころの一つだと思っていて、URPやHDRPを使ってみたいけど、よ...

カメラの設定を見直す

次に二つ目はカメラの設定を見直すことです。Unityでは基本的にカメラに写っているオブジェクトに対して描画処理が走るので、例えばカメラの撮影範囲を狭めることで余計なオブジェクトが映らないようにして処理を削減することができます。

やり方は簡単で、Cameraコンポーネントの「クリップ面」の「ファー」の値を小さくすればOKです(下図)。

カメラのカリング設定

また、後述するオクルージョンカリングを行う場合は「オクルージョンカリング」にチェックが入っていることを確認しましょう。

これはすぐにできる最適化なのでぜひ試してみてください。

メッシュを結合する

三つ目はメッシュを結合することです。シーンに別々のメッシュがたくさん存在している場合、1つ1つに対して描画処理が呼び出されるので負荷が高くなりがちです。そこでもし可能であれば、近くにあるメッシュ同士を結合することで描画負荷を軽減することができます

ただし残念ながらUnityの標準機能ではメッシュを結合できないので、パッケージの「Probuilder」のメッシュ結合機能を使うか、アセットストアで「Easy Mesh Combiner MT」のようなメッシュ結合用のアセットを購入する必要があります。

あと「メッシュを結合するとよい」と書くと勘違いされがちなのですが、何でもかんでも結合すればいいというわけではないので注意してください。原則として近くに密集しているメッシュを一つに結合するのが一番効果的で、逆に広範囲に散っているメッシュを結合してしまうと十分な効果が得られない場合があります(カメラに一部でも映っているメッシュには描画処理が走る点を考慮してもらえばその理由がよく分かると思います)。なのでメッシュを結合する際は粒度を考えて実行するようにしましょう。

マテリアルを統一する

四つ目はできるだけマテリアルを統一することです。メッシュレンダラーに登録されているマテリアルがバラバラだとその分だけ描画コストが増える場合があるので、例えば同じ色のマテリアルが複数あるならそれを同じマテリアルに統一する、といった工夫が必要です。

ただしURPを採用している場合は、「SRP Batcher」という最適化機能がありマテリアルのシェーダーが同じなら描画コストを抑えられる場合もあります。

テクスチャサイズを見直す

さて五つ目はテクスチャサイズを見直すことです。アセットストアで3Dモデル等を購入した場合、高解像度のテクスチャ(4096px四方とか)がそのままインポートされることが多くゲームの容量が激増したりメモリを圧迫したりします。なので特にスマホ用ゲームの場合はテクスチャサイズには十分に気を付ける必要があるでしょう。

テクスチャサイズの変更方法はすごく簡単で、テクスチャ設定の一番下の「最大サイズ」を適当に小さくするだけです。

テクスチャのインポート設定

スマホゲームの場合は大きくても「512」程度で十分でしょう。またPCゲームの場合でもリアルさ重視のゲームでなければ「1024」か、大きくても「2048」のサイズがあれば事足ります。

ライトを使い分ける

六つ目はライトを適切に使い分けることです。ゲームを作っているとポイントライトを乱用しがちですが、ポイントライトは重いのでシーンに置きまくると負荷が掛かってしまいます。そこで場合によってはスポットライト等に置き換えることで描画コストを減らすことができます。

ただしURPを採用している場合は、シーンにたくさんライトを置いても特定のライトしか有効にならないようになっているのであまり気にしなくてもよいかもしれません。

あと、リアルタイムライトとそれによる影は負荷が高いので、なるべくライティングをベイクするようにしておくとベストです。

Terrainの設定を見直す

七つ目はTerrainの設定を見直すことです。3Dゲームでフィールドを作るときによく使われるTerrainは、巷では重いといわれがちですが実は設定次第でかなり負荷を軽くすることができます

Terrainの最適化については以下の記事で詳しくご紹介しているので、そちらも併せてご覧ください。

【Unity】重いTerrainの描画処理を軽くする方法
Unityでオープンワールドゲームを作るときなど、広大な地形を扱う場合はほぼ確実にTerrain(テレイン)機能を使うことになると思います。好きな地形をUnityエディタ上で手軽に作れるのはとても便利ですよね。しかし、Terrainの大きな...

ポストプロセスを使いすぎない

八つ目はポストプロセス(URP・HDRPの場合はVolumeを使いすぎないことです。ポストプロセスを使うと良い感じの絵作りをすることができますが、例えばBloomやDepth Of Fieldなどは描画負荷が結構増えるので注意が必要です。本当に必要なものだけを有効化するようにしましょう。

LODグループを上手く使う

九つ目はLODグループを上手く使うことです。LODとは「Level Of Detail」の略で、カメラからの距離に応じてメッシュを雑に表示することで描画負荷を下げる機能のことです。

LODグループについてはUnity公式マニュアルをご覧ください。

LOD グループ - Unity マニュアル
LODGroupコンポーネントは、ゲームオブジェクトのLevelofDetail(LOD)を管理するために使います。

シェーダーを軽量なものに変える

10個目はマテリアルのシェーダーを軽量なものに変更することです。例えばURPなら

  • Lit
  • Complex Lit
  • Simple Lit
  • Unlit

といったシェーダーが標準で用意されており、デフォルトでは「Lit」が採用されていますが、これを適宜「Simple Lit」や「Unlit」に変更することで高速化が見込めます。特にスマホゲームの場合に効果を実感しやすいと思うのでシェーダーの変更も検討してみてください。

オクルージョンカリングを使う

最後はオクルージョンカリングを使うことです。オクルージョンカリングとは、簡単に言えば隠れていて見えないメッシュを非表示にすることで描画負荷を軽減する手法です。

オクルージョンカリングの使い方については以下の記事で詳しく説明していますので併せてご覧いただければと思います。

【Unity】オクルージョンカリング(Occlusion Culling)を使って描画処理を最適化する方法
Unityでオープンワールドゲーム等の3Dゲームを作っていると、描画処理の負荷が気になることが多いですよね。そこで私は今まで色々な最適化処理を学んできたのですが、一つだけイマイチ使い方がよく分からない最適化機能がありました。それは「オクルー...

物理演算の最適化

次は物理演算の最適化についてです。物理演算の処理を軽くするための主なテクニックとしては次のようなものがあります。

  1. なるべくメッシュコライダーを使わない
  2. 固定時間ステップを大きくする

なるべくメッシュコライダーを使わない

まず一つ目はなるべくメッシュコライダーを使わないことです。メッシュコライダーは簡単に複雑な形状の当たり判定を付けられる代わりに、処理が複雑なのでかなり高い負荷が掛かってしまいます。したがって可能であれば

  • スフィアコライダー
  • カプセルコライダー
  • ボックスコライダー

といった単純なコライダーを使うことを検討してみてください。

固定時間ステップを大きくする

次に二つ目は、プロジェクト設定から固定時間ステップの値を大きくすることです。

Unityの時間設定

固定時間ステップの値が小さいほど物理演算が正確になりますがその分処理が重くなります。まあたいていのゲームではデフォルト設定のままでOKですが、スマホゲームなどでは値を大きくして負荷を下げるのも良いかもしれません。

C#スクリプトの最適化

さて最後はC#スクリプトの最適化についてです。これについては以下の記事で詳しくご紹介しているのでそちらをご覧いただければと思います。

【Unity】C#スクリプトの処理を軽くするための基本テクニックまとめ
今回はUnityの最適化に関する話題で「C#スクリプトの処理を軽くするための基本テクニック」をまとめてみるという内容です。Unityで作ったゲームが重くなる原因はザックリ分けて描画関係の処理が重い(=GPUに負荷がかかる)スクリプトの処理が...

一応概要を簡単にまとめておくと、

  • 重い関数はUpdate関数などから頻繁に呼び出さないようにする
  • なるべく高速な関数を使う

といった感じです。C#スクリプトの書き方が悪いと処理が重くなりがちなので注意しましょう。

おわりに

以上、長くなってしまいましたがUnityで自作ゲームを最適化する方法をまとめてみました。ご紹介したテクニックの中には比較的簡単に最適化できる方法もいくつかあるので、是非それだけでも試して頂ければと思います。

この記事がゲーム開発のお役に立てば幸いです。