UnityでのNull合体演算子の使用に関する注意点
Unityを使用してゲーム開発を行う中で、コンポーネントの取得や追加を効率的に書く方法として、C#のNull合体演算子(??)
を利用することが考えられます。この記事では、その使用方法と注意点について説明します。
基本的なコード:
以下のコードは、Rigidbody2D
コンポーネントがアタッチされているか確認し、なければ追加する処理です。
void Test1()
{
rigidbody2D = GetComponent<Rigidbody2D>();
if(rigidbody2D == null)
{
rigidbody2D = gameObject.AddComponent<Rigidbody2D>();
Debug.Log("Test1 Rigidbody2Dがなかったためアタッチされました。");
}
}
Null合体演算子を使った短縮形:
上記のコードは、Null合体演算子を使用して以下のように短縮することができます。
void Test2()
{
rigidbody2D = GetComponent<Rigidbody2D>() ?? gameObject.AddComponent<Rigidbody2D>();
Debug.Log($"Test2 {rigidbody2D}");
}
しかし、この短縮形を使用した場合、意図した通りにrigidbody2D
がセットされない場合があります。
void Test3()
{
rigidbody2D = GetComponent<Rigidbody2D>();
Debug.Log($"Test3 {rigidbody2D == null}");
Debug.Log($"Test3 {rigidbody2D is null}");
}
== null
と is null
は、一般的にC#で同じような動作をすると考えられていますが、Unityの特定の状況やシナリオでは異なる結果を返すことがあります。
==
演算子は、特定のクラスでオーバーロードされている場合、そのオーバーロードされた動作を行います。Unityの UnityEngine.Object
クラス(およびそのサブクラス)は ==
演算子をオーバーロードしており、破棄されたオブジェクトや未参照のオブジェクトを null
として扱うようにしてあります。
一方で、is
キーワードは参照が実際にnullであるかどうかを確認します。そのため、UnityEngine.Object
のインスタンスが破棄されているか、アクセス可能でない場合、== null
はtrue
を返すのに対して、is null
はfalse
を返す場合があります。
この挙動は、Unityの UnityEngine.Object
の特性に由来しており、他のC#の環境やフレームワークではこのような挙動は発生しないことが多いです。