LessonEX よくあるエラー
エラーまとめ
Unityの授業内で頻出したエラーをまとめて解決法を書いておくことで、後輩の助けになるといいねって感じのページです。随時更新。
エラーを意図的に起こして条件を確認し、対処法を記述していきます。どの解説も新規プロジェクト、新規シーンを想定しています。
デバッグについては3Dアクションゲーム編3-3も参考にしてください。
【一覧】
・NullReferenceException:Object reference not set to an instance of an object
・MissingComponentException:There is no 〇〇 attached to the △△ game object, but a script is trying to access it.
・IndexOutOfRangeException: Index was outside the bounds of the array.
・NullReferenceException:
Object reference not set to an instance of an object
起こりやすさ :★★★★★
修正難易度 :★★☆☆☆
「オブジェクトが存在しない」といった意味のエラーで、存在しない物を操作しようとした結果発生します。俗にいう「ぬるぽ」です。
基本的にケアレスミスなので対処は容易ですが、発生しやすいため注意しましょう。
【意図的に起こす】
適当なスクリプトを作成し、以下のコードを記述してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sample : MonoBehaviour
{
void Update()
{
// エンターキーが押されたら
if (Input.GetKeyDown(KeyCode.Return))
{
// プレイヤータグがついたオブジェクトを上に移動させる
GameObject.FindGameObjectWithTag("Player").transform.position
+= new Vector3(0.0f, 10.0f, 0.0f);
}
}
}
このスクリプトはEnterキーが押されたら「Player」タグがついたオブジェクトを検索し、そのオブジェクトを上へ移動させるというものです。
コードが書けたら適当な空オブジェクトにアタッチしてください。

この状態でゲームを実行し、Enterキーを押すとエラーが発生するはずです。
シーン上にPlayerタグがついたオブジェクトが存在しないため、エラーが発生しています。「存在しないものは操作できないよ!」といった感じです。
【解決策】
前述のパターンではPlayerタグがついたオブジェクトを配置することで対応できます。

このエラーが発生した時は、まずエラー文をダブルクリックしてエラー発生個所を確認し「取得しようとしているオブジェクトが本当に存在しているか」を確認しましょう。

特にスクリプトで動的に生成しているオブジェクトを取得する場合は、まだシーン上に生成されていないオブジェクトを操作しようとした結果、このエラーが発生することがあります。ゲームが複雑化すると、このタイプのエラーの方が多くなると思われます。
簡単に対策する方法としては「オブジェクトが存在しない場合は操作しない」という処理を追加する方法があります。FindGameObjectWithTag関数は指定したタグのオブジェクトが存在しなかった場合はnullを返すので、nullかどうかで分岐することで存在しないオブジェクトの操作を防ぐことができます。

このエラーに限った話ではないですが、エラーが発生した時は落ち着いてエラー個所を確認し、原因を確認するようにしましょう。
・MissingComponentException:
There is no 〇〇 attached to the △△ game object, but a script is trying to access it.
起こりやすさ:★★★☆☆
修正難易度 :★☆☆☆☆
取得しようとしたコンポーネントがアタッチされていない場合に発生します。〇〇には取得しようとしたコンポーネント名、△△には取得対象のオブジェクト名が表示されます。
上記のオブジェクト参照エラーに似ていますが、こちらの方が少し対処しやすいです。うっかりコンポーネントのアタッチを忘れることは多いので、落ち着いて対処できるように慣れていきましょう。
【意図的に起こす】
適当なスクリプトを作成し、以下のコードを記述してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sample : MonoBehaviour
{
void Update()
{
// エンターキーが押されたら
if (Input.GetKeyDown(KeyCode.Return))
{
// 自分にアタッチされたRigidbodyに力を加える
GetComponent<Rigidbody>().AddForce(Vector3.up, ForceMode.Impulse);
}
}
}
このスクリプトはEnterキーが押されたら自身にアタッチされているRigidbodyコンポーネントを取得し、AddForce関数で上方向に力を加えています。
コードが書けたら適当な空オブジェクトにアタッチしてください。
オブジェクトにRididbodyコンポーネントがアタッチされていないと、Enterキーを押した際に上記のエラーが発生します。
【解決策】
シンプルに対象オブジェクトに必要なコンポーネントをアタッチすればOKです。

GetComponent関数もコンポーネントを取得できなかった場合はnullを返すため、nullかどうかで分岐することもできます。
例えば対象オブジェクトにそのコンポーネントがアタッチされているかわからない場合や、動的にコンポーネントを操作している場合に有効です。

・IndexOutOfRangeException: Index was outside the bounds of the array.
起こりやすさ:★★★☆☆
修正難易度 :★★★☆☆
範囲外の配列にアクセスしようとした場合に発生します。
配列とは変数を順番に並べたボックスのようなものです。「配列の1番に1を入れる」「配列の4番を取得する」といったように、番号を使って配列にアクセスします。
しかし、用意していない配列番号を使用した場合、上記のエラーが発生するのです。

【意図的に起こす】
適当なスクリプトを作成し、以下のコードを記述してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sample : MonoBehaviour
{
// int型の配列を要素数5つで作成
public int[] Numbers = new int[5];
void Start()
{
// 用意していない要素番号へのアクセスは実行時にエラー
Numbers[10] = 10;
}
}
このスクリプトはStart関数内でint型の配列10番に10を代入する処理を行っています。
しかし、int型の配列Numbersは要素数が5つのため、範囲外にアクセスしたことによるエラーが出ています。
【解決策】
配列の要素数を増やすか、アクセスする要素番号が範囲内に収まるようにしてください。
特に配列の要素数を動的に操作している場合は注意が必要です。