Unityにおける Destroy と MissingReferenceException の理解と活用方法
目次
1. 概要
Unityでオブジェクトを削除する Destroy
の正しい使い方や、削除に伴うエラー(MissingReferenceException
)を防ぐ方法を解説します。また、インスペクターやコンソールでのエラーや警告の違いについても触れます。
2. Destroy
の基本動作
Destroy
は、指定されたオブジェクトを 次のフレームのタイミング で削除します。削除直後のフレーム中では、オブジェクトにまだアクセス可能なため、適切な処理が必要です。
基本的なコード例
using UnityEngine;
public class DestroyExample : MonoBehaviour
{
public GameObject myObject;
void Start()
{
// myObjectを削除
Destroy(myObject);
// 現在のフレームではまだアクセス可能
Debug.Log("Current frame: " + myObject.name);
// 次のフレームで確認
Invoke("CheckAfterDestroy", 0.1f);
}
void CheckAfterDestroy()
{
// 次のフレームでオブジェクトは削除済み
Debug.Log("Next frame: " + myObject.name); // MissingReferenceException が発生
}
}
3. 注意点とエラーの回避
3.1 NullReferenceException と MissingReferenceException の違い
エラータイプ | 原因 |
---|---|
NullReferenceException | 変数が null の状態でプロパティやメソッドにアクセスした場合に発生。 |
MissingReferenceException | Unityオブジェクトが Destroy によって削除された後、まだ参照を持っている場合に発生。 |
3.2 NullReferenceException の例
using UnityEngine;
public class NullReferenceExample : MonoBehaviour
{
private GameObject myObject;
void Start()
{
// myObjectが初期化されていないため、以下でエラーが発生
Debug.Log(myObject.name);
}
}
3.3 MissingReferenceException の例(GetComponentの場合を含む)
using UnityEngine;
public class MissingReferenceExample : MonoBehaviour
{
public GameObject myObject;
void Start()
{
// オブジェクトを削除
Destroy(myObject);
// 次のフレームで参照しようとするとエラーが発生
Invoke("CheckAfterDestroy", 0.1f);
}
void CheckAfterDestroy()
{
Debug.Log(myObject.name); // MissingReferenceException が発生
}
}
さらに、GetComponent
を使用してコンポーネントを取得しようとした場合も同様のエラーが発生することがあります。
using UnityEngine;
public class GetComponentExample : MonoBehaviour
{
void Start()
{
// Rigidbodyが存在しない場合
Rigidbody rb = GetComponent<Rigidbody>();
// rbがnullなので以下でエラーが発生
Debug.Log(rb.mass); // MissingReferenceException が発生
}
}
4. インスペクターとコンソールでの違い
4.1 コンソールでの表示
MissingReferenceException
は コンソールウィンドウ にエラーとして表示されます。
- 例:
MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
4.2 インスペクターでの表示
インスペクターでは、以下の状況で「Missing」と表示されることがあります:
スクリプト自体が削除されている場合
- 「Script: Missing」と表示されます。
参照オブジェクトが失われている場合
- スクリプト内のフィールドで指定されていたオブジェクトが削除されている場合、フィールドが「Missing」となります。
5. DestroyとDestroyImmediateの違い
メソッド | 動作 |
---|---|
Destroy | オブジェクトを次のフレームで削除します。現在のフレームではアクセス可能です。 |
DestroyImmediate | オブジェクトを即座に削除します。現在のフレームで参照するとエラーが発生します。 |
DestroyImmediate の例
using UnityEngine;
public class DestroyImmediateExample : MonoBehaviour
{
public GameObject myObject;
void Start()
{
DestroyImmediate(myObject);
// 即座にエラーが発生
Debug.Log(myObject.name); // NullReferenceException が発生
}
}
6. 削除後の適切な参照チェック方法
削除後にエラーを回避するため、null
チェックを行うことが重要です。
6.1 基本的な Null チェック
if (myObject != null)
{
Debug.Log("オブジェクトはまだ有効です。");
}
else
{
Debug.Log("オブジェクトは削除されています。");
}
6.2 Unity特有の Null チェック
Unityのオブジェクトでは if (myObject)
を簡潔に利用することもできます。
if (myObject)
{
Debug.Log("オブジェクトはまだ有効です。");
}
else
{
Debug.Log("オブジェクトは削除されています。");
}
7. まとめ
Destroy 使用時のポイント
Destroy
は次のフレームでオブジェクトを削除します。削除直後にアクセスするときは注意。- 即座に削除する必要がある場合は
DestroyImmediate
を慎重に使用。 - 削除されたオブジェクトを参照する場合は、
null
チェックを徹底する。
よくあるエラーの回避策
- NullReferenceException を防ぐには、変数の初期化を忘れない。
- MissingReferenceException を防ぐには、削除されたオブジェクトへの参照を適切に管理する。
学習のための課題
- 各サンプルコードをシーンに配置して動作を確認してください。
Destroy
とDestroyImmediate
の違いを再現し、挙動の違いを体験してください。- コンソールとインスペクターでの表示の違いを確認してください。
この資料を活用して、エラーの原因と解決方法を理解し、実践的なスクリプト作成に役立ててください。
ディスカッション
コメント一覧
まだ、コメントがありません