Skip to content

1st term 6th week

Daisuke Suzuki edited this page Jun 17, 2021 · 1 revision

今回のテーマ

トラブルシュート(問題が起きた時に、原因を調べて直すこと)に必要なことを学ぶ。

今回の内容

トラブルシュートの基本として以下について学ぶ。

  • null
  • 例外
  • null チェック
  • コンパイル エラー
  • ランタイム エラー
  • デバッグ実行

準備

  1. CSharp1-1-6.unitypackage をダウンロードして前回使ったプロジェクトにインポートする
    • 前回使ったプロジェクトがない場合は、新しくプロジェクトを作ってインポートする
  2. Project のフォルダ "_06 Troubleshooting" の下にあるシーンを開いて実行し、動くことを確認しておくこと

null とは

null(ヌル)とは「何もない」という意味で、クラス型の変数にインスタンスが代入されていない状態のことを指す。この時、変数 a は null である、と言う。

クラス型の変数の初期値は null である。

クラス型の変数が null である時、そのメンバーを呼び出すと、エラー (NullReferenceException) になる。この「エラーになる」という表現は正確ではなく、正確には「例外 (exception) がスロー (throw) される」という。

例外とは

例外とは、プログラムの実行中に本来、または通常とは違う状態にあることを言う。例外がスローされた時(エラーになった時)に、その例外を try ~ catch 句で捕捉 (catch, handle) しなければ、通常の Windows アプリケーションでは強制終了(クラッシュ)してしまう。ただし、Unity 上で動いているプログラムで例外がスローされた時は、その例外は Unity によって捕捉され、Console にその例外の内容が記録される。Unity もしくは Unity で作ったアプリケーションは強制終了しないが、関数内の例外がスローされた後の処理は実行されない

Unity を使っている場合、経験する例外のほとんどは NullReferenceException であるが、以下のような例外を経験する場合もある。

  1. IndexOutOfRangeException - 配列のインデックスに範囲外の値を指定した時にスローされる。ロジックの誤りにより発生する。解決方法としては、ロジックの誤りを直して、範囲内のインデックスを指定するようにプログラムを修正する。
  2. UnassignedReferenceException - Unity 独自の例外。public や [SerializeField] を使ってメンバー変数に Inspector から値をアサインするように作られているのに、何もアサインされず変数が null のまま変数のメンバーにアクセスした時にスローされる。解決方法としては、該当のプロパティに Inspector から値をアサインする。
  3. MissingComponentException - Unity 独自の例外。追加されていないコンポーネントを操作しようとした時にスローされる。解決方法としては、該当のコンポーネントを GameObject に追加する。

例外はルールとして〇〇Exception という名前が付けられている。

課題(各2点)

  1. シーン "1 Exception" を開いて実行し、左クリックするとエラーが Console に記録される。この問題の原因を特定し、解決せよ。
  2. 同様に、何度か左クリックするとエラーが Console に記録される。この問題の原因を特定し、解決せよ。
  3. 同様に、右クリックするとエラーが Console に記録される。この問題の原因を特定し、解決せよ。

null チェックとは

クラス型の変数が null である可能性がある時、そのままメンバーを呼び出すと例外がスローされるおそれがある。そのため、変数が null である可能性がある場合は、以下のように変数が null であるかどうかを確認してからメンバーを呼び出す。

Transform t;    // この状態では t は null である
if (t != null)
{
    Debug.Log(t.position);    t  null ではないことを確認してからメンバーを呼び出す
}

Unity が用意しているクラスの場合は、「変数が null ではない時 bool 型で true、null の時 bool 型で false を返す」という特別な仕様があるため、null チェックを以下のように書くことができる。

Transform t;    // この状態では t は null である
if (t)
{
    Debug.Log(t.position);    t  null ではないことを確認してからメンバーを呼び出す
}

また、C# の「null 条件演算子 "?"」を使って以下のように書くこともできる。この書き方は Unity の場合に限定されておらず、C# そのものの仕様である。

Transform t;    // この状態では t は null である
Debug.Log(t?.position);    // t? と書くと、t が null ではない場合のみメンバーを呼び出す

課題(5点)

  1. シーン "2 NullCheck" を開いて実行し、あることをすると Console にエラーが記録される。この原因を特定し、null チェックをすることにより解決せよ。

エラーの種類 (Unity)

Unity では Console にエラー(※)が表示された時には注意が必要である。エラーには種類があり、それぞれ適切な対応をしなければならない。

(※)マークと共に表示されるメッセージが「エラー」である。なお、は「警告」、は「情報」である。「警告」は「問題であるとは限らないが、問題かもしれない」程度の意味であり、これが表示されていても「実行できない」ということはない。

コンパイル エラー

コンパイル エラーは、C# の文法エラーである。Unity が C# で書かれたスクリプトに対してコンパイルという解釈する作業をした時に、文法に誤りがあるために解釈できないことで起きるエラーである。見分け方としては、エラーに "error CSxxxx"(xxxx は4桁の数字)という文字列が含まれる。このエラーが起きている間は、シーンを実行することができない。実行しようとすると "All compiler errors have to be fixed before you can enter playmode!" と表示され、実行できない。解決するにはメッセージの通り、文法エラーを修正しなければならない。

エラーの意味を知りたい時は、エラー コードである CSxxxx(xxxx は4桁の数字)を検索する。エラーメッセージを機械翻訳しても、大抵の場合はその意味を理解することはできないでしょう。

なお、このエラーは Console の Clear ボタンをクリックしても消すことはできない。Clear ボタンをクリックしてもエラーが消えない場合は、そのエラーを解決する必要がある。

下のパネルに表示されているエラーの情報は、選択してコピーすることができる。エラーについて人に質問する時は、ここに表示されている情報を全てコピーして伝えること。

ランタイム エラー

ランタイム(Runtime、実行時)エラーとは、プログラムを実行中に例外がスローされ、それが Unity によってハンドルされて記録されるエラーである。見分け方としては、先頭に〇〇Exception と表示される

下のパネルに表示されているエラーの情報は、選択してコピーすることができる。エラーについて人に質問する時は、ここに表示されている情報を全てコピーして伝えること。

その他のエラー

上の2つに分類されないエラーとしては、アプリケーションをビルドした時のビルドエラーや、Unity の内部的なエラー(ウィンドウレイアウト機能の不具合など)がある。これらのエラーについては、そのエラーメッセージから判断し、内容に応じて対応する必要がある。

デバッグ実行

問題が起きた時にプログラムの内容を調べて問題の原因を調べることを「デバッグ」という。この時、Console.WriteLine() や Debug.Log() を使ってプログラムのどこが実行されたか調べたり、変数の内容を出力して想定通りに動いているか調べることを「print デバッグ」と言う。これはもっとも原始的なデバッグの方法である。

Visual Studio を使っている場合は「デバッグ実行」することによりブレークポイントでプログラムの実行を一時停止したり、一時停止中に変数の中身を除いたり、ステップ実行により一行ずつプログラムの実行を進めることができる。これは C# で Windows アプリケーションを作る時にも、Unity でゲームを作る時にも非常に役立つので、積極的に使っていくこと。

参照

参照

  • 『確かな力が身につく C#「超」入門 第2版』
    • null についての記述はない
    • コンパイル エラー
      • 2-2 プロジェクトの作成から実行まで - プログラムに間違いがあった場合
  • 『独習 C# 新版』
    • null
      • 2.5.2 null 値