「昨日まで動いていたのに」「赤いエラーが出たけど英語で読めない」——プログラミングにバグはつきものです。優れた開発者とは、バグを書かない人ではなく、 バグを効率的に見つけ出して直せる人 のこと。この作業が デバッグ です。
Unityにはデバッグを助けるツールがいくつも用意されています。この記事では、最も手軽なDebug.Logの使い方、エラーメッセージ(特に定番のNullReferenceException)の読み解き方、そしてデバッガによるステップ実行まで、初心者が知っておくべき基礎を解説します。
この記事でわかること
Debug.Log/LogWarning/LogErrorの使い分け- エラーメッセージの読み方と、エラー行へのジャンプ方法
- 最頻出エラー
NullReferenceExceptionの原因と対処- デバッガ(ブレークポイント)を使ったステップ実行の始め方
最も簡単なデバッグツール: Debug.Log()
Debug.Log()は、指定したメッセージをUnityエディタのコンソールウィンドウに出力するメソッドです。これは、プログラムの特定の部分が実行されているかを確認したり、その時点での変数の値を確認したりするための、最もシンプルで効果的な方法です。
using UnityEngine;
public class DebugExample : MonoBehaviour
{
private int score = 0;
void Start()
{
// ゲーム開始時にメッセージを出力
Debug.Log("ゲームが開始されました。");
}
void Update()
{
// ボタンが押されたかを確認
if (Input.GetKeyDown(KeyCode.Space))
{
score += 10;
// 現在のスコア変数の値を出力
Debug.Log("スペースキーが押されました。現在のスコア: " + score);
}
}
}
コンソールウィンドウは、Unityエディタ上部のWindow > General > Consoleから開くことができます。
補足: 変数を出力するときは、
"スコア: " + scoreのような文字列連結より、 文字列補間$"スコア: {score}"が読みやすくおすすめです。Debug.Log($"位置: {transform.position}, HP: {hp}")のように複数の値も1行でまとめられます。もう1つの小技が 第2引数 で、Debug.Log("被弾!", gameObject)のように渡しておくと、Consoleのその行をクリックしたときに 発生元のオブジェクトがHierarchyでハイライト されます。「同じログがどの敵から出たのか」を探す時間がゼロになります。
Debug.LogWarning() と Debug.LogError()
Debugクラスには、メッセージの重要度に応じて使い分けるためのバリエーションがあります。
Debug.LogWarning(): 警告メッセージ(黄色のアイコン)を出力します。エラーではないが、注意すべき状況(例: 設定されていないオプションがあるなど)で使います。Debug.LogError(): エラーメッセージ(赤色のアイコン)を出力します。プログラムの実行に支障をきたす致命的な問題が発生したときに使います。

これらを使い分けることで、コンソールログが整理され、問題の重 要度を素早く把握できます。
エラーメッセージの読み解き方
プログラムに問題があると、Unityはコンソールに赤色のエラーメッセージを表示します。初心者のうちはこのエラーメッセージに圧倒されてしまうかもしれませんが、落ち着いて読めば、問題解決のための重要なヒントが書かれています。
よくあるエラー: NullReferenceException
これは「ぬるぽ」としても知られる、最も頻繁に遭遇するエラーの一つです。「実体のない(nullの)オブジェクトのメソッドやプロパティにアクセスしようとした」ときに発生します。
イメージは「中身が入っているはずの箱を開けたら空だった」です。変数という箱はあるのに、実体への参照が入っていない状態でメソッドを呼ぶと、このエラーが発生します。

原因の例:
GetComponent<T>()でコンポーネントを取得しようとしたが、実際にはアタッチされていな かった。- Inspectorウィンドウで設定すべき
public変数が設定されていない(空のまま)。
// 例: Rigidbodyがアタッチされていないのにアクセスしようとした
public class NullRefExample : MonoBehaviour
{
private Rigidbody rb;
void Start()
{
// ここでrbに何も代入されない
}
void FixedUpdate()
{
// rbはnullなので、ここでNullReferenceExceptionが発生する
rb.AddForce(Vector3.up);
}
}
対処法:
エラーメッセージをダブルクリックすると、エラーが発生したコードの行にジャンプできます。その行で使われている変数がnullになっていないか、Debug.Logで確認したり、if (variable != null)でチェックしたりして原因を特定します。
デバッガを使ったステップ実行
Debug.Logは手軽ですが、プログラムの実行を止めて、その瞬間のすべての変数の状態をじっくりと観察したい場合もあります。そのような高度なデバッグを可能にするのがデバッガです。
Visual StudioやRiderといったコードエディタには、Unityと連携するデバッガが内蔵されています。
基本的な使い方:
- ブレークポイントの設定: コードエディタで、調査したいコードの行の左側をクリックして、赤い丸(ブレークポイント)を設定します。
- Unityにアタッチ: コードエディタの「Unityにアタッチ」ボタン(通常は再生ボタンのようなアイコン)を押して、デバッガをUnityエディタに接続します。
- ゲームの実行: Unityエディタでゲームを再生します。
- 実行の中断: プログラムの実行がブレークポイントを設定した行に到達すると、そこで一時停止します。
- 変数の確認とステップ実行: 実行が停止した状態で、コードエディタのデバッグウィンドウに変数の値一覧が表示されます。ここから、「1行進む(ステップオーバー)」「関数の中に入る(ステップイン)」などの操作を行い、プログラムの動きを1行ずつ詳細に追跡できます。

デバッガの使いこなしは少し慣れが必要ですが、複雑なバグを解決するための最強の武器となります。
実践:「攻撃が当たるのにHPが減らない」を捜査する
道具の説明はここまでです。ここからは、実際の開発で毎週のように起きるバグ——剣は敵に当たっているのに、HPバーが減らない——を、1件の事件として捜査してみましょう。アクションRPGの攻撃、シューティングの被弾、パズルのスコア加算——「処理が届いていないように見える」バグの捜査手順は全部同じです。

「ログをたくさん置いて眺める」のではなく、 仮説を1つずつ、いちばん安い道具で潰していく のがプロの手順です。
- 再現手順を固定する: 「この敵に、この位置から、攻撃を1回」のように、 毎回同じ操作で必ず起きる最短の手順 を先に決めます。再現が曖昧なままだと、直ったかどうかも判定できません
- Consoleの「最初の」例外を読む: 赤いエラーが複数出ていたら、見るのは 一番上(最初に起きたもの)だけ です。後続のエラーは巻き添えのことが多いからです。
NullReferenceException: ...の下のスタックトレースから、 自分の書いたコードの一番上の行(例:EnemyHealth.TakeDamage () (at Assets/_Project/Scripts/EnemyHealth.cs:24))をダブルクリックして飛びます - 該当行の「容疑者」を挙げる: 24行目が
healthBar.SetValue(current);なら、nullの容疑者はhealthBarです。 行の中のドット(.)の左側に並んでいるものが容疑者リスト ——この読み方だけで、NullReferenceの捜査は半分終わります - ブレークポイントで実値を見る: 該当行にブレークポイントを置いて手順1を再現し、
damage・target・healthBarの 実際の値 を見ます。「思っていた値」と「実際の値」のズレが犯人です - Inspectorの設定を疑う: コードが正しくても、Inspectorの
healthBar欄がNone(割り当て忘れ)、敵のLayerがEnemyではなくDefault——といった 設定側の犯人 も同じくらい多いです。再生中にPauseして、Hierarchyで現物を確認します - 直したら、同じ手順でもう一度: 手順1とまったく同じ操作で、「1回の攻撃でちょうど10減る」ことを確認します。違う操作で確認すると、直っていなくても直ったように見えることがあります
エラーが出ないときの切り分け
赤いエラーが出るバグは、実は簡単な部類です。厄介なのは 「エラーは出ないのに減らない」 パターン。同じ症状でも、犯人によって最短ルートが変わります。
| 症状 | よくある犯人 | 最短の道具 |
|---|---|---|
| 赤いエラーが出る | healthBarやtargetの未設定(NullReference) | Console → スタックトレース → 該当行 |
| エラーも出ず、HPも減らない | 攻撃判定のLayer違いで、そもそもTakeDamageが呼ばれていない | 入口にブレークポイント( 止まらなければ手前が犯人 ) |
| HPが2回ずつ減る | イベントの二重購読(OnEnableで+=、-=し忘れ) | Debug.Logで呼び出し回数を数える → 購読箇所を検索 |
覚えておきたいのは、 ブレークポイントは「止まらないこと」自体が重要な証拠 だということです。TakeDamageの1行目に置いて止まらなければ、犯人はこのメソッドの中ではなく、呼び出す側の配線(Layer・Collider・イベント登録)にいます。捜査範囲が一気に半分になります。
捜査の締めくくりは、派手な道具ではなく手順6の「同じ手順でもう一度」です。エラー文から行番号へ飛び、ブレークポイントで実際の値をのぞき、最後に最初と同じ攻撃でちょうど10減るのを見届ける——この流れを一度自分の手で通せたら、次のバグからは「どこから見ればいいか」で迷わなくなります。
おまけ:先に知っておくと良いこと
Debug.Logとデバッガに慣れたら、Unityにはさらに強力な「見える化」の道具があります。
- シーンビューに図形を描いてデバッグ: 敵の索敵範囲やレイの軌跡など、「数値では分かりにくい空間的な情報」は Gizmos でシーンビューに直接描画できます。Gizmos入門の記事 で解説しています。
- 「重い」の原因を数値で特定: カクつきの調査は勘ではなく Profiler で。どの処理に何ミリ秒かかっているかを実測できます。Profiler入門の記事 が参考になります。
- バグを未然に防ぐ側へ: 手動確認の代わりにテストコードで自動チェックする Unity Test Framework という選択肢もあります。Test Framework入門の記事 で始め方を掴めます。
まとめ
デバッグは、試行錯誤のプロ セスです。エラーを恐れず、むしろ問題解決への手がかりとして活用する姿勢が重要です。
Debug.Logを積極的に使う: 変数の値やプログラムの通過点を気軽に確認しよう。- エラーメッセージをよく読む: 問題の種類と発生場所が書かれている宝の地図です。
NullReferenceExceptionを警戒する: オブジェクトやコンポーネントが正しく設定・取得されているか常に意識しよう。- デバッガに挑戦する: 複雑な問題に直面したら、デバッガを使ってプログラムの内部を覗いてみよう。
これらのデバッグスキルを身につけることで、開発のスピードと品質は飛躍的に向上します。