【Unity・C#】ゲーム開発中によく見かけるエラーとその対処法まとめ

Unity・C# 遭遇しやすいエラー Unity

今回はゲーム開発で悩みのタネになりがちなエラーに関する話題で、

Unityでのゲーム開発で遭遇しやすい主なエラーとその対策

をいくつかご紹介するという内容になっています。

Unityでゲームを作っていると必ずと言っていいほど何らかのエラーに遭遇するのですが、私の経験上よく見かけるエラーは大体決まっているので、初心者の方向けにその辺の対策をまとめておいたらお役立ていただけるのではないかと思いました。

そこでここではUnityやC#でありがちなエラーをご紹介し、ついでに対策についても簡潔に説明しておきますね。

Unityでのゲーム開発で遭遇しやすいエラーとその対処法

ではさっそくUnityでのゲーム開発で遭遇しやすいエラーとその対策をご紹介していきます。エラーの種類は色々あると思いますが、大きく分けると次の三つに分類できます。

  • 文法ミス(コンパイルエラー)
  • 例外
  • その他のエラー

それぞれ詳しく見ていきましょう。

文法ミス(コンパイルエラー)

まずは文法ミスによって起きるエラー(主にコンパイルエラー)です。文法ミスをするとそもそもコンパイルに通らずゲームを実行できないので、この手のエラーが出たら真っ先に直す必要があります。ただし文法ミスがあればVisual Studio等の開発環境が即座に教えてくれるため、一番直しやすいエラーだと言えるでしょう。

Unityでよく見る文法ミスは次のようなものが挙げられます。

  1. 行末のセミコロン忘れ
  2. カッコの閉じ忘れ
  3. スペルミスや大文字・小文字の区別の間違い

行末のセミコロン忘れ

一つ目は行末のセミコロン(;)忘れです。C#の場合はセミコロンを忘れるとエラーになってしまうので気を付けましょう。

カッコの閉じ忘れ

二つ目はカッコの閉じ忘れです。これは特に

  • 入れ子になっているif文
  • カッコを多用する複雑な計算式・条件式

を書いたときに閉じ忘れをすることが多いでしょう。このような場合は適宜インデントを入れるなどすると分かりやすくなります。

スペルミスや大文字・小文字の区別の間違い

三つ目はスペルミスです。例えば「AddDownforce」という関数を定義したとき、その関数を呼び出す際に「AddDownForce(=forceのFが大文字)」「AddDownfoce(=rが抜けている)」と書いてしまった場合にも文法ミスとなります。

このようなミスは非常によくあるので、対策としては

  • 正しいスペルで書く(これ重要。綴りが怪しければ面倒でもちゃんと調べること
  • どの部分を大文字にするかを予めきちんと決めておく(※プログラミングでよくあるこのような命名規則を「キャメルケース」といいます。詳細はググってください)

といったことが挙げられます。

例外

お次は例外です。例外とはプログラムにおいて想定外の事象が起きることで、基本的にプログラムの実行中に発生します。厳密に言うとエラーとは違うのですがここでは便宜的に一緒に紹介しておきます。

なお例外に関しては予め対策を打っておくことでプログラム側で対処することができるのが特徴です(※例外に対処する処理を「例外処理」といいます)。例外処理の詳細についてはググってみてください。

さてUnityでよく見かける例外をいくつか挙げると次のようなものがあります。

  1. NullReferenceException
  2. IndexOutOfRangeException
  3. InvalidOperationException
  4. KeyNotFoundException

NullReferenceException

まずNullReferenceExceptionUnityでゲームを作っていると最もよく遭遇する例外で、簡単に言えば「参照が存在しないものにアクセスしようとした」ときにスローされます。例えば次のC#スクリプトのような場合です。

using System.Collections.Generic;
using UnityEngine;

public class ErrorSample : MonoBehaviour
{

    Rigidbody rb = null;

    void Start()
    {
        ErrorMethod();
    }

    void ErrorMethod()
    {
        rb.AddForce(Vector3.up);
    }

}

上記のスクリプトでは参照が何もない変数の関数を呼び出しているのでNullReferenceExceptionが発生します。

ちなみにNullReferenceExceptionはC#スクリプト内だけでなくインスペクター上で必要な参照を登録し忘れたときにも発生します。うっかりミスが多い人ほど頻繁にこの例外を見る羽目になるので「またか…」とうんざりすること間違いなしでしょう。

IndexOutOfRangeException

IndexOutOfRangeExceptionは、配列などにおいて範囲外のインデックスを使って要素にアクセスしようとしたときにスローされる例外です。例えば次のC#スクリプトではこの例外が発生します。

using System.Collections.Generic;
using UnityEngine;

public class ErrorSample : MonoBehaviour
{

    int[] nums = { 1, 2, 3 };

    void Start()
    {
        ErrorMethod();
    }

    int ErrorMethod()
    {
        return nums[3];
    }

}

上のスクリプトだと、配列numsは(要素が3つでなので)0~2以外のインデックスではアクセスできないのに、「3」というインデックスでアクセスしているからダメということですね。

この例外の対策としては

  • そもそも範囲外のインデックスを使えないようにする
  • 範囲外のインデックスでアクセスしようとしたら処理を中断する

といったことが考えられます。

InvalidOperationException

次にInvalidOperationExceptionは、無効なメソッド呼び出しが行われた場合にスローされる例外です。この例外を最もよく見かける場面は、次のようにfor文やforeach文の中でコレクションの要素を削除しようとするときです。

using System.Collections.Generic;
using UnityEngine;

public class ErrorSample : MonoBehaviour
{

    List<int> sampleList = new List<int> { 1, 2, 3 };

    void Start()
    {
        ErrorMethod();
    }

    void ErrorMethod()
    {
        foreach(int num in sampleList)
        {
            sampleList.Remove(num);
        }
    }

}

こういったコードは例外が発生するのでダメです。覚えておきましょう。

KeyNotFoundException

KeyNotFoundExceptionはディクショナリ(=辞書)等において、存在しないキーでアクセスしようとするとスローされる例外です。サンプルは次のC#スクリプトのとおり。

using System.Collections.Generic;
using UnityEngine;

public class ErrorSample : MonoBehaviour
{

    Dictionary<string, int> sampleDict = new Dictionary<string, int> { { "sample01", 1 } , { "sample02", 2 }, { "sample03", 3 } };

    void Start()
    {
        ErrorMethod();
    }

    int ErrorMethod()
    {
        return sampleDict["sample00"];
    }

}

対策としては、例えばディクショナリであればContainsKeyメソッドがあるので、それでキーが存在するかどうかをチェックしてから処理を行うといったことが挙げられます。

その他のエラー

最後は上記以外のエラーについてです。

  1. クラス名とC#スクリプトファイル名の不一致によるエラー
  2. 削除したC#スクリプトへの参照が残ったままのエラー

クラス名とC#スクリプトファイル名の不一致によるエラー

一つ目はクラス名とC#スクリプトファイル名の不一致によるエラーです。例えば

  • C#スクリプト名:ErrorSample
  • C#スクリプト内のクラス名:ErrorTest

といった場合にこのエラーが発生する場合があります。したがってクラス名とC#スクリプトのファイル名は同じものにしましょう。

なお「発生する場合がある」というのは、厳密に言うとこのエラーはMonoBehaviourを継承しているクラスで発生するということです。MonoBehaviourを継承しないクラス(例えば自分で勝手に追加したクラス)の場合は全く関係ありません。

削除したC#スクリプトへの参照が残ったままのエラー

二つ目はゲームオブジェクトにC#スクリプトをアタッチした後、そのスクリプトを削除すると発生するエラーです。下の図のように「該当するスクリプトをロードできません」というエラー文が表示されます。

該当するスクリプトをロードできません

このままでもゲームを実行することができますが、警告文が出て鬱陶しいのでこのエラーが出ているコンポーネントは削除しておきましょう。

おわりに

以上、Unityでゲーム開発をしているとよく遭遇するエラーについて説明し、対策もご紹介しました。

初心者のうちは次々とエラーが出て焦ってしまう…ということも多いかと思いますが、エラーはミス等を教えてくれる大切な機能なので怖がらずに丁寧に対処していただければと思います。また、すでにご紹介した通りUnityでのゲーム開発で見かけるエラーは大体決まっているため、上記の内容を覚えて頂ければ開発もスムーズに進むようになると思います。ぜひ参考になさってください。

この記事がUnityでのゲーム開発のお役に立てば幸いです。