---
title: Unityプログラミング ベストプラクティス
product: Unity Editor
version: '6000.0'
latest_version: '7000.0'
status: This page documents version 6000.0. The latest version is 7000.0.
canonical: https://docs.unity.com/ja-jp/engine/6000.0/manual/scripting/optimization/programming-best-practices
latest_url: https://docs.unity.com/ja-jp/engine/7000.0/manual/scripting/optimization/programming-best-practices.md
generated_at: 2026-11-14T04:23:49.018Z
locale: ja-jp
---

# Unityプログラミング ベストプラクティス

> Unityアプリケーションのコードを記述する際に注意すべきキー問題と、よくある落とし穴を回避するのに役立つベストプラクティス。

Unity のプログラミング環境の一意の機能の中には、標準の C#/.NET プロジェクトと比較してコード作成時に余分な考慮が必要なものがあります。以下のサマリーは、Unityアプリケーションのコードを記述する際に注意すべきキー問題と、よくある落とし穴を回避するのに役立つベストプラクティスです。

## Unity オブジェクトライフサイクルと参照##unity-object-lifecycle-and-references

Unity で C# を記述する場合、他のオブジェクトや null と等しいオブジェクトを比較するときは注意してください。[UnityEngine.オブジェクト](/engine/6000.0/manual/scripting/object-oriented-development/fundamental-unity-types/class-object.md)から継承する型の場合、Unity は C# の[等式および不等式](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators)演算子のカスタムバージョンを使用します。つまり、null チェック`myGameObject == null`は、技術的には有効な C# オブジェクトリファレンスを保持している場合でも、`myGameObject` が`true`を評価できます (また、逆に、`myGameObject != null` は`false`を評価できます)。この動作の詳細については、[カスタム等値演算](/engine/6000.0/manual/scripting/object-oriented-development/fundamental-unity-types/class-object.md#custom-equality-comparers)子 を参照してください。

Unity のカスタムの等値動作とオブジェクト ライフサイクルは、コードにいくつかの影響を与えます。

* チェックで破棄されたオブジェクトを確実に除外したい場合は、Unity オブジェクトに `if (obj == null)` ではなく `ReferenceEquals` を使用してください。
* 実際の C# null 参照を確認する場合は、最初に `ReferenceEquals` または `System.Object` にキャストします。
* 2 つの Unity オブジェクトが等しいかどうかを比較する場合、例えば[`Undo`](/engine/6000.0/script-reference/unityeditor/undo.md)によって、一方または両方が破棄されて再作成されると、両方の参照が異なる C# オブジェクトであっても`obj1 == obj2`が`true`を返す場合があります。
* カスタムの等値演算子は、標準の C# 演算子よりも遅くなります。これは通常問題ではありませんが、スケールとホット パスでは注意が必要です。
* 保護せずにシーンのアンロード間でコンポーネントをキャッシュしません。なぜなら、コンポーネントは破棄される可能性があるが、アンマネージの相手を持たない C# ラッパーオブジェクトとして残っているからです。
* 静的フィールドで大きなアセットへの強い参照を保持しないでください。なぜなら、アセットはシーン全体に保持され、アンロードできなくなるからです。
* オブジェクトを破棄する場合、[`Object.DestroyImmediate`](/engine/6000.0/script-reference/unityengine/object/destroyimmediate.md)はエディターのみであるため、ランタイムに[`Object.Destroy`](/engine/6000.0/script-reference/unityengine/object/destroy.md)を使用し、Unity に破棄のスケジュールを設定させます。

## C# ファイナライザーを避ける##avoid-c-finalizers

以下の理由により、ランタイムコードで [C# ファイナライザー](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/finalizers)を使用しないでください。

* これらは別のファイナライザースレッドで実行され、Unity API には通常メインスレッドが必要です。
* これらは非決定論的に実行されるため、予測できない動作が発生します。
* アプリケーションのガベージが収集されて待機しない限り、まったく実行されない可能性があります。
* ファイナライザーからスローされた例外は、特殊な処理を行わない限り、アプリケーションの停止を引き起こす可能性があります。
* その存在自体が、ガベージ コレクターのオーバーヘッドを増加させます。

## ガベージ コレクターのオーバーヘッドと割り当て##garbage-collector-overhead-and-allocations

Unityアプリケーションで最も重要なパフォーマンス リスクの1つは、メモリを割り当て、特にホット パスでガベージ コレクターのオーバーヘッドを増加させるランタイム コードです。

これを回避するには、以下のコーディング方法を適用します。

* [リストをキャッシュ](/engine/6000.0/manual/scripting/optimization/performance-optimizing-code-managed-memory/reusable-code.md)して再利用し、可能な場合は割り当てないバージョンのメソッドを使用して、フレームごとの割り当てを回避します。これには、[`WaitForSeconds`](/engine/6000.0/script-reference/unityengine/waitforseconds.md)のキャッシュや、[コルーチン](/engine/6000.0/manual/scripting/object-oriented-development/coroutines-section/coroutines.md)使用時のその他[の yield 命令](/engine/6000.0/script-reference/unityengine/yieldinstruction.md)が含まれます。
* 可能な場合は、割り当てないバージョンのメソッドを使用し、[`Update`](/engine/6000.0/script-reference/unityengine/monobehaviour/update.md) から繰り返し呼び出すのではなく、[`Awake`](/engine/6000.0/script-reference/unityengine/monobehaviour/awake.md)内の[`GameObject.GetComponent`](/engine/6000.0/script-reference/unityengine/gameobject/getcomponent.md)や返されたオブジェクトへのキャッシュ参照などの負荷の高い操作を実行してください。
* ランタイム コード、特にフレームごとの`Update`や`FixedUpdate`、その他のホット パスのコンテキストで [LINQ](https://learn.microsoft.com/en-us/dotnet/csharp/linq/) を使用することは避けてください。`System.Linq` 名前空間のメソッドは不必要な割り当てを作成し、ボックス化やクロージャを伴う場合があります。
* 連結などの[文字列操作の繰り返し](/engine/6000.0/manual/scripting/optimization/performance-optimizing-code-managed-memory/reference-types.md)を避けます。
* リフレクションのインスタンスを特定して回避します。詳細は、「 [C# リフレクション オーバーヘッド](/engine/6000.0/manual/analysis/performance-memory/managed-memory/gc-avoid-reflection.md)の回避 」を参照してください。

これらの問題の詳細なガイダンスと例については、 マネージ[メモリーのコード最適化](/engine/6000.0/manual/scripting/optimization/performance-optimizing-code-managed-memory.md) を参照してください。

ガベージコレクターのオーバーヘッドの追跡と削減については、[マネージメモリ](/engine/6000.0/manual/analysis/performance-memory/managed-memory.md) を参照してください。

## MonoBehaviour 更新ループ最適化##monobehaviour-update-loop-optimization

多くの Unity プロジェクトでは、MonoBehaviour スクリプトコンポーネントを使用して、[`MonoBehaviour.Update`](/engine/6000.0/script-reference/unityengine/monobehaviour/update.md)、[`MonoBehaviour.FixedUpdate`](/engine/6000.0/script-reference/unityengine/monobehaviour/fixedupdate.md)、[`MonoBehaviour.LateUpdate`](/engine/6000.0/script-reference/unityengine/monobehaviour/lateupdate.md) などのビルトインコールバックを使用してゲームステートを定期的に更新するのが従来のパターンです。これらのコールバックは通常、1 秒間に何度も実行されます。

これは、適切に使用すればまだうまく機能する単純なモデルですが、経験の浅い開発者が陥りやすいいくつかのキーなパフォーマンスリスクがあります。

* Unity のフレーム単位やその他の通常のイベント機能のデフォルト実装は、スケールが不良な場合があります。これらの各`Update`機能には、Unityの内部管理とネイティブ レイヤーとのインタラクションによるわずかなオーバーヘッドが発生します。このような MonoBehaviour スクリプトが多数ある場合は、累積オーバーヘッドがパフォーマンスに大きな影響を与える可能性があります。
* ビルトイン更新は頻繁に実行されるため、ホットコードパスとなり、そこに配置した非効率的でメモリー負荷の高い操作のエフェクトが大きくなります。経験の浅いユーザーが陥りやすい悪いパターンは、`Update` 関数を持つ MonoBehaviour スクリプトが多くあり、そのスクリプトがほとんどの場合に不必要に実行されたり、実行時にメモリに不必要に負荷がかかることです。

これらのリスクを軽減するには、以下のオプションを検討してください。

* 多くのエンティティでスケーラビリティを向上させるために、UnityのECS([エンティティ コンポーネント システム)](https://docs.unity3d.com/Packages/com.unity.entities@latest)を使用してプロジェクトをデータ指向アーキテクチャに変換することを検討してください。

* MonoBehaviour ベースのアーキテクチャを使用する場合

  * ホットパスでのマネージメモリの影響を最小限に抑えるには、「 マネージメモリの[コード最適化](/engine/6000.0/manual/scripting/optimization/performance-optimizing-code-managed-memory.md) 」を参照してください。
  * 集中管理された更新マネージャを使用するかプレイヤーループをカスタマイズすることで、アクティブな`Update`機能の数を最小化。詳細については、「 [カスタム更新マネージャー](/engine/6000.0/manual/scripting/object-oriented-development/managing-update-order/events-per-frame-optimization.md)の使用 」および「 [プレイヤーループのカスタマイズ](/engine/6000.0/manual/scripting/object-oriented-development/managing-update-order/player-loop-customizing.md) 」を参照してください。
  * MonoBehaviour ベースのプロジェクトでも、Unity のデータ指向システムの特定の機能を使用することがよくあります。コードの[ジョブ](/engine/6000.0/manual/scripting/optimization/job-system.md)や[Burstコンパイル](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-compilation/burst.md) セクションの使用、コードのパフォーマンス クリティカルなセクションでの[`NativeArray`](/engine/6000.0/script-reference/unity/collections/nativearray1.md)などのより効率的なデータ構造の使用、[Transform操作](/engine/6000.0/manual/transformhandle-landing.md)などのアンマネージAPIの代替手段の選択が可能です。

## スレッドセーフティ##thread-safety

Unity はマルチスレッド機能を備えていますが、コアランタイムはシングルスレッドであり、`UnityEngine` 名前空間と `UnityEditor` 名前空間のほとんどの API はメインスレッドからのみ呼び出すことができます。背景グラウンドスレッドからGameObjectsオブジェクト、Transform、コンポーネント、アセット API をリファレンスしないでください。メインスレッドで`Task.Result`や`Task.Wait`を`await`しないでください。デッドロックにつながるからです。

本質的に非同期で長時間実行される操作を処理する場合、Unityは.NET `Task`に代わるUnity固有のオプションとして[`Awaitable`](/engine/6000.0/script-reference/unityengine/awaitable.md)クラスを提供します。`Awaitable`はオブジェクトプールを使用して割り当てを削減し、`Update`や`FixedUpdate`などのUnity固有の概念を認識します。これにより、タスクを`await`し、プレイヤーループの特定の時点で再開するようにスケジュール設定することができます。詳細は、「 Awaitable クラスを使用した[非同期プログラミング](/engine/6000.0/manual/scripting/optimization/async-await-support.md) 」を参照してください。

生存期間が短いが演算負荷が高い並列作業のために、Unityは[Burstコンパイル](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-compilation/burst.md)可能な[ジョブ システム](/engine/6000.0/manual/scripting/optimization/job-system.md)を提供します。詳細については、「 ジョブシステムでの[マルチスレッドコードの記述](/engine/6000.0/manual/scripting/optimization/job-system.md) 」を参照してください。

## コンパイルに関する考慮事項##compilation-considerations

最適なパフォーマンスを得るには、コードの記述方法だけでなく、コンパイル方法も考えることが重要です。コードの特定のソースファイルまたは地域がどのコンテキストに関連するかをアクティブに定義するのではなく、コードを単純コンパイルすると、以下のコストがかかります。

* 不要なコードが含まれている場合はビルドサイズを増やす。
* 変更を適用するためのコンパイルと再コンパイルに要した時間。これは特に、エディターでのイテレーション時間に影響します。
* 特定のプラットフォームまたはコンテキストに不適切なコードが含まれている場合、ランタイム エラーが発生する可能性があります。

Unity には、コードのどの部分を異なるプラットフォームやコンテキスト用にコンパイルするかのコントロールに役立つメカニズムがいくつか用意されています。

* アセンブリ定義を使用すると、ソースファイルを、個別にコンパイルできるアセンブリにグループ化できます。これにより、エディターのみのコードをランタイムコードから、プラットプラットフォーム固有のコードをクロスプラットフォームコードから分離できます。詳細については、[スクリプトのアセンブリ](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-compilation/assembly-definition-files.md)への整理 を参照してください。
* [スクリプトシンボル](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-compilation/conditional-compilation/symbol-reference.md)とともに `#if` 指示子を使用すると、ターゲットプラットフォームまたはコンテキストに基づいて、特定のコード地域をコンパイルから除外できます。例えば、`#if UNITY_EDITOR` ディレクティブの背後にあるエディターのみのコードをガードして、ランタイムビルドから除外します。Unity が条件付きでコードを含む/除外するために提供するさまざまな方法の詳細は、[条件付きコンパイル](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-compilation/conditional-compilation/platform-dependent-compilation.md) を参照してください。
* Unity 固有のキー概念は、再生モードの開始と終了、またはスクリプトの再コンパイル時のエディターでの[ドメインリロード](/engine/6000.0/manual/scripting/compilation-and-code-reload/code-reloading-editor/configurable-enter-play-mode.md)です。ドメインの再ロードは時間がかかり、エディターでの記述やテストのイテレーション時間に影響する可能性があります。再生モードの開始時にドメインのリロードを使用不可にしてイテレーション時間を短縮できますが、静的ステートを手動でリセットする必要があります。詳細は、『 [コードと再生モード](/engine/6000.0/manual/scripting/compilation-and-code-reload/code-reloading-editor.md)開始時のシーンリロード 』を参照してください。

## Unityの分析ツール##unity's-analysis-tools

Unity は、ボトルネックを特定し、よりパフォーマンスの高いコードを書くのにヘルプつさまざまなツールを提供しています。[Project Auditor](/engine/6000.0/manual/project-auditor.md) ツールは、プロジェクトコードを分析して、一般的なパフォーマンスの問題を特定し、修正を提案できます。[プロファイラー](/engine/6000.0/manual/analysis/profiler.md)は、CPU と GPU の使用状況、メモリーアロケーションなどの詳細情報を提供することで、コードのランタイムパフォーマンスのボトルネックを特定するのに役立ちます。また、[Roslyn アナライザー](https://learn.microsoft.com/en-us/visualstudio/code-quality/roslyn-analyzers-overview?view=visualstudio)を作成して、コーディング標準を適用し、プロジェクトに固有のパフォーマンスの問題を特定することもできます。

カスタム Roslyn アナライザーとソースジェネレーターの作成の詳細は、[Roslyn アナライザーとソースジェネレーター](/engine/6000.0/manual/scripting/debugging-and-diagnostics/roslyn-analyzers.md) を参照してください。

Unityの分析ツール スイートの詳細については、[最適化](/engine/6000.0/manual/analysis.md)を参照してください。

## 追加リソース##additional-resources

* [Unity のメモリ](/engine/6000.0/manual/analysis/performance-memory.md)
* [マネージメモリー用のコードの最適化](/engine/6000.0/manual/scripting/optimization/performance-optimizing-code-managed-memory.md)
* [デバッグと診断](/engine/6000.0/manual/scripting/debugging-and-diagnostics.md)
