• ゲーム
  • Industry
  • リソース
  • コミュニティ
  • 学習
  • サポート
開発
Unityエンジン
任意のプラットフォーム向けに2Dおよび3Dゲームを構築
ダウンロードプランと価格
収益化
アプリ内課金(IAP)
ストア全体でIAPを発見し、管理する
Mediation
収益を最大化し、マネタイズを最適化する
Ad Quality
アプリのユーザーエクスペリエンスを保護する
Tapjoy
長期的なユーザーの忠誠心を構築する
すべてのマネタイズ製品
詳しく見る
詳しく見る
発見され、モバイルユーザーを獲得する
UnityベクターAI
プレイヤーを適切なゲームに接続する
Auraのオンデバイス広告
ピークエンゲージメント時にデバイス上のユーザーにリーチする
すべての成長製品
活用事例
3Dコラボレーション
リアルタイムで3Dプロジェクトを構築およびレビューする
没入型トレーニング
没入型環境でのトレーニング
顧客体験
インタラクティブな3D体験を作成する
すべての業界ソリューション
業界
製造業
運用の卓越性を達成する
小売
店内体験をオンライン体験に変換する
自動車
革新と車内体験を高める
全業界
技術ライブラリ
ドキュメント
公式ユーザーマニュアルとAPIリファレンス
開発者ツール
リリースバージョンと問題追跡
ロードマップ
今後の機能をレビューする
用語集
技術用語のライブラリ
インサイト
ケーススタディ
実際の成功事例
ベストプラクティスガイド
専門家のヒントとコツ
すべてのリソース
新機能
ブログ
更新情報、情報、技術的ヒント
お知らせ
ニュース、ストーリー、プレスセンター
コミュニティハブ
ディスカッション
議論、問題解決、つながる
イベント
グローバルおよびローカルイベント
コミュニティストーリー
Made with Unity
Unityクリエイターの紹介
ライブストリーム
開発者、クリエイター、インサイダーに参加する
Unity Awards
世界中のUnityクリエイターを祝う
すべてのレベルに対応
Unity Learn
無料でUnityスキルをマスターする
プロフェッショナルトレーニング
Unityトレーナーでチームをレベルアップ
Unity初心者向け
スタートガイド
学習を開始しましょう
Unityエッセンシャルパスウェイ
Unity は初めてですか?旅を始めましょう
ハウツーガイド
実用的なヒントとベストプラクティス
教育
学生向け
キャリアをスタートさせる
教育者向け
教育を大幅に強化
教育機関向けライセンス
Unityの力をあなたの機関に持ち込む
認定教材
Unityのマスタリーを証明する
サポートオプション
ヘルプを得る
Unityで成功するためのサポート
Success Plan
専門的なサポートで目標を早く達成する
FAQ
よくある質問への回答
お問い合わせ
私たちのチームに連絡する
プランと価格
言語設定
  • English
  • Deutsch
  • 日本語
  • Français
  • Português
  • 中文
  • Español
  • Русский
  • 한국어
ソーシャル
通貨
購入
  • プロダクト
  • Unity Ads
  • サブスクリプション
  • Unity Asset Store
  • リセラー
教育
  • 学生
  • 教育関係者
  • 教育機関
  • 認定資格試験
  • 学ぶ
  • スキル開発プログラム
ダウンロード
  • Unity Hub
  • ダウンロードアーカイブ
  • ベータプログラム
Unity Labs
  • ラボ
  • 研究論文
リソース
  • Learn プラットフォーム
  • コミュニティ
  • ドキュメント
  • Unity QA
  • FAQ
  • サービスのステータス
  • ケーススタディ
  • Made with Unity
Unity
  • 当社について
  • ニュースレター
  • ブログ
  • イベント
  • キャリア
  • ヘルプ
  • プレス
  • パートナー
  • 投資家
  • アフィリエイト
  • セキュリティ
  • ソーシャルインパクト
  • インクルージョンとダイバーシティ
  • お問い合わせ
Copyright © 2025 Unity Technologies
  • 法規事項
  • プライバシーポリシー
  • クッキーについて
  • 私の個人情報を販売または共有しないでください

「Unity」の名称、Unity のロゴ、およびその他の Unity の商標は、米国およびその他の国における Unity Technologies またはその関係会社の商標または登録商標です(詳しくはこちら)。その他の名称またはブランドは該当する所有者の商標です。

Hero background image

高度なプログラミングとコードアーキテクチャ

グラフィックスのレンダリングをさらに最適化するために、コードアーキテクチャを探求してください。今回は、Unityプロジェクトの最適化のヒントを紹介する連載の第4回目です。より少ないリソースでより高いフレームレートで動作させるためのガイドとしてご利用ください。これらのベストプラクティスを試したら、シリーズの他のページもぜひご覧ください:パフォーマンス向上のためのUnityプロジェクトの設定 ハイエンドグラフィックスのパフォーマンス最適化 PCおよびコンソールゲームのGPU使用量の管理 スムーズなゲームプレイのための物理演算パフォーマンスの向上
このウェブページは、お客様の便宜のために機械翻訳されたものです。翻訳されたコンテンツの正確性や信頼性は保証いたしかねます。翻訳されたコンテンツの正確性について疑問をお持ちの場合は、ウェブページの公式な英語版をご覧ください。
ここをクリックしてください。
  • UnityのPlayerLoopを理解しましょう
  • カスタム・アップデート・マネージャーの構築
  • 毎フレーム実行されるコードの最小化
  • 高価な関数の結果をキャッシュ
  • 空のUnityイベントとデバッグ・ログ文の回避
  • スタックトレースのロギングを無効にします。
  • 文字列パラメータの代わりにハッシュ値を使用
  • オブジェクトをプール
  • ScriptableObjects のパワーを活用しましょう。

UnityのPlayerLoopを理解しましょう

UnityのPlayerLoopには、ゲームエンジンのコアと対話するための関数が含まれています。この構造には、初期化とフレームごとの更新を処理する多くのシステムが含まれています。すべてのスクリプトは、このPlayerLoopに依存してゲームプレイを作成します。プロファイリングを行うと、プロジェクトのユーザーコードがPlayerLoopの下に表示され、EditorコンポーネントはEditorLoopの下に表示されます。

UnityのFrameLoopの 実行順序を理解することは重要です。すべてのUnityスクリプトは、いくつかのイベント関数を決められた順序で実行します。Awake、Start、Updateなど、スクリプトのライフサイクルを作成する関数の違いを学び、パフォーマンスを強化します。

例えば、Rigidbodyを扱うときにUpdateではなくFixedUpdateを使ったり、ゲーム開始前に変数やゲームの状態を初期化するときにStartではなくAwakeを使ったりします。これらを使って、各フレームで実行されるコードを最小限に抑えます。Awakeはスクリプトのインスタンスが生きている間に一度だけ呼び出され、常にStart関数の前に呼び出されます。つまり、他のオブジェクトと会話できることが分かっているオブジェクトを扱うときや、初期化されたオブジェクトに問い合わせるときは、Startを使用する必要があります。

イベント関数の具体的な実行順序については、スクリプトのライフサイクルのフローチャートを参照してください。

カスタム Update マネージャーの図

カスタム・アップデート・マネージャーの構築

プロジェクトに厳しいパフォーマンス要件がある場合(オープンワールドゲームなど)、Update、LateUpdate、またはFixedUpdateを使用してカスタムUpdate Managerを作成することを検討してください。

UpdateまたはLateUpdateの一般的な使用パターンは、何らかの条件が満たされたときにのみロジックを実行することです。このため、この条件をチェックする以外、事実上何のコードも実行しないフレームごとのコールバックが多数発生する可能性があります。

UnityがUpdateやLateUpdateのようなメッセージメソッドを呼び出すときはいつも、インターオプコール、つまりC/C++側からマネージドC#側へのコールを行います。少数のオブジェクトについては、これは問題ではありません。何千ものオブジェクトがあると、このオーバーヘッドが大きくなってきます。

アクティブなオブジェクトがコールバックを必要とする場合は、この Update Manager にサブスクライブし、そうでない場合はアンサブスクライブします。このパターンによって、Monobehaviourオブジェクトへのインターオプ呼び出しの多くを減らすことができます。

実装例については、ゲームエンジン固有の最適化テクニックを参照してください。

毎フレーム実行されるコードの最小化

コードが毎フレーム実行されなければならないかどうかを検討してください。Update、LateUpdate、FixedUpdateから不要なロジックを削除できます。これらのUnityイベント関数は、毎フレーム更新しなければならないコードを置くのに便利な場所ですが、その頻度で更新する必要のないロジックを抽出することができます。

ロジックを実行するのは、状況が変化したときだけです。特定の関数シグネチャをトリガーするイベントの形で、オブザーバーパターンなどのテクニックを活用することを忘れないでください。

Updateを使用する必要がある場合は、nフレームごとにコードを実行します。これは、重いワークロードを複数のフレームに分散させる一般的な手法であるタイムスライシングを適用する方法の1つです。

この例では、ExampleExpensiveFunctionを3フレームに1回実行します。

コツは、他のフレームで実行される他の作業と、この作業を織り交ぜることです。この例では、Time.frameCount % interval == 1またはTime.frameCount % interval == 2のときに、他の高価な関数を「スケジュール」することができます。

あるいは、カスタム・アップデート・マネージャ・クラスを使用して、サブスクライブされたオブジェクトをnフレームごとに更新します。

高価な関数の結果をキャッシュ

2020.2より前のバージョンのUnityでは、GameObject.Find、GameObject.GetComponent、Camera.mainが高価な場合があるので、Updateメソッドで呼び出すのは避けた方が良いでしょう。

さらに、OnEnableと OnDisableに高価なメソッドを置くのは避けましょう。これらのメソッドを頻繁に呼び出すと、CPUスパイクの原因となります。

可能な限り、次のような高価な関数を実行します。 のような高価な関数を実行します。や MonoBehaviour.Startなどの高価な関数を初期化フェーズで実行します。必要な参照をキャッシュし、後で再利用します。スクリプトの実行順序の詳細については、以前のUnity PlayerLoopのセクションをチェックしてください。

繰り返されるGetComponent呼び出しの非効率的な使用を示す例を示します:

void 更新()
{
Renderer myRenderer = GetComponent<Renderer>();
ExampleFunction(myRenderer);
}

代わりに、関数の結果がキャッシュされるため、GetComponentを1回だけ呼び出します。キャッシュされた結果は、GetComponent を再度呼び出すことなく Update で再利用できます。

イベント機能の実行順序については、こちらをご覧ください。

空のUnityイベントとデバッグ・ログ文の回避

ログステートメント(特にUpdate、LateUpdate、FixedUpdate)はパフォーマンスを低下させる可能性があるため、ビルドを行う前にログステートメントを無効にしてください。これを素早く行うには 条件属性を作ることを検討してください。

例えば、以下のようなカスタム・クラスを作成したいとします。

カスタムクラスでログメッセージを生成します。 プレイヤー設定>スクリプトのシンボル定義で ENABLE_LOGプリプロセッサを無効にすると、すべてのログステートメントが一挙に消えます。

文字列やテキストの扱いは、Unityプロジェクトでパフォーマンスの問題を引き起こす一般的な原因です。そのため、ログ文とその高価な文字列書式を削除することで、パフォーマンスが大きく向上する可能性があります。

同様に、空のMonoBehavioursはリソースを必要とするので、空白のUpdateまたはLateUpdateメソッドを削除する必要があります。テストにこれらの方法を使う場合は、プリプロセッサ・ディレクティブを使ってください:

#if UNITY_EDITOR
void 更新()
{
}
#endif

ここでは、不要なオーバーヘッドがビルドに入り込むことなく、Update in Editorをテストに使用できます。

10,000回のUpdateコールに関するこのブログ記事では、UnityがどのようにMonobehaviour.Updateを実行するかについて説明しています。

スタックトレースのロギングを無効にします。

プレーヤー設定の スタックトレースオプションを使用して、表示されるログメッセージのタイプを制御します。アプリケーションがリリースビルドでエラーや警告メッセージを記録している場合(例えば、クラッシュレポートを生成するため)、パフォーマンスを向上させるためにスタックトレースを無効にしてください。

スタックトレースのロギングについてはこちらをご覧ください。

文字列パラメータの代わりにハッシュ値を使用

Unityでは、Animator、Material、Shaderのプロパティのアドレスに文字列名を使用することはありません。高速化のために、すべてのプロパティ名はプロパティIDにハッシュ化され、これらのIDはプロパティをアドレス指定するために使用されます。

アニメーター、マテリアル、シェーダーでSetメソッドやGetメソッドを使用する場合は、文字列値のメソッドではなく、整数値のメソッドを活用してください。文字列値メソッドは文字列のハッシュを実行し、ハッシュされた ID を整数値メソッドに転送します。

使用 を使用します。を使います。 Shader.PropertyToIDを使用します。

関連するのはデータ構造の選択で、これはフレームごとに何千回も反復するため、パフォーマンスに影響します。正しい構造を選択するための一般的なガイドとして、C#におけるデータ構造に関するMSDNガイドに従ってください。

オブジェクトプールのスクリプトインターフェース

オブジェクトをプール

Instantiateと Destroyは、ガベージコレクション(GC)スパイクを発生させる可能性があります。これは一般的に時間のかかる処理なので、GameObjectを定期的にインスタンス化して破棄する(銃で弾を撃つなど)のではなく、再利用やリサイクルが可能な事前割り当てオブジェクトのプールを使用します。

再利用可能なインスタンスは、CPUスパイクが目立ちにくい、メニュー画面やローディング画面のようなゲーム中の時点で作成します。このオブジェクトの「プール」をコレクションで追跡します。ゲームプレイ中は、必要なときに次の利用可能なインスタンスを有効にし、オブジェクトを破壊する代わりに無効にしてからプールに戻すだけです。これは、プロジェクト内の管理された割り当ての数を減らし、GC問題を防ぐことができます。

同様に、実行時にコンポーネントを追加することは避けてください。Unityは、実行時にコンポーネントを追加するたびに、重複するコンポーネントやその他の必要なコンポーネントをチェックする必要があります。必要なコンポーネントがすでにセットアップされたPrefabをインスタンス化する方がよりパフォーマンスが高いので、オブジェクトプールと組み合わせて使用してください。

関連して、Transformを移動させるときは Transform.SetPositionAndRotationを使用して、位置と回転の両方を一度に更新します。これにより、Transformを2回修正するオーバーヘッドを避けることができます。

実行時にGameObjectをインスタンス化する必要がある場合、最適化のために親オブジェクトと再配置する必要があります。

Object.Instantiate の詳細については、スクリプティング API を参照してください。

Unityでシンプルなオブジェクトプーリングシステムを作成する方法はこちらをご覧ください。

スクリプタブルオブジェクトプール

ScriptableObjects のパワーを活用しましょう。

MonoBehaviour の代わりに ScriptableObject に不変の値や設定を保存します。ScriptableObject はプロジェクト内に存在するアセットです。一度だけ設定する必要があり、GameObjectに直接アタッチすることはできません。

ScriptableObject にフィールドを作成して値や設定を保存し、MonoBehaviours で ScriptableObject を参照します。ScriptableObjectのフィールドを使用することで、そのMonoBehaviourを持つオブジェクトをインスタンス化するたびにデータが重複するのを防ぐことができます。

ScriptableObjects入門の チュートリアルをご覧ください。

ユニティ・キー・アート21 11
無料電子書籍を入手

これまでで最も包括的なガイドの1つで、PCとコンソール向けにゲームを最適化する方法について、80以上の実用的なヒントを集めています。当社のエキスパートであるサクセスとアクセラレート・ソリューションズのエンジニアが作成したこれらの詳細なヒントは、Unityを最大限に活用し、ゲームのパフォーマンスを向上させるのに役立ちます。

e ブックをダウンロード

このコンテンツにご満足いただけましたか?

はい!

満足しました

いいえ。

いまいちでした