Help us understand the problem. What is going on with this article?

GameObjectやComponentをnullと比較するときの落し穴

More than 1 year has passed since last update.
    [SerializeField] private GameObject target; // 参照している。nullじゃない。

    private void Awake()
    {
        Debug.Log(target == null); // Falseと表示される
        DestroyImmediate(target);
        Debug.Log(target == null); // Trueと表示される
    }

上のコードは、Unityにいくつかある「はまりポイント」や「なんじゃこりゃってなるポイント」の一つです。

変数targetがオブジェクトを参照していてnullじゃないのに、target == nulltrue

解説

GameObjectComponent==オペレーターを使って、target == nullのように評価する際、変数がオブジェクトを参照しているのにも関わらず、trueと評価されることがあります。

これらの親クラスであるUnityEngine.Objectには、==!=boolのオペレーターが定義されています。

そして、その挙動が「対象のGameObjectComponentが、生存していないならば、==nullと比較するとtrueを返す」という仕様になっています

内部でこんなメソッドを作って生存しているかチェックをしています。

  • IsNativeObjectAlive
  • DoesObjectWithInstanceIDExist

この挙動は、私はあまり好きではありません。「コードは、利用者の期待や予測に対して、驚きが最小であるべき」と思っています。この挙動は、==に対して利用者が予期しない「生存チェックもする」という驚きを与えてしまっています。

覚えておかないと、予期せぬバグを発生させることがあるので、注意が必要ですね。(多分、ごくまれに発生するめんどいバグを生み出す原因になりそう)

次のコードを見てみることもオススメします。

https://github.com/Unity-Technologies/UnityCsReference/blob/2018.2/Runtime/Export/UnityEngineObject.bindings.cs#L100

おまけ。対応策

変数が参照するオブジェクトが破壊されるケースがあり、純粋にnullと比較したい場合System.Object.ReferenceEqualsを使うことをオススメします。

    [SerializeField] private GameObject target; // 参照している。nullじゃない。

    private void Awake()
    {
        Debug.Log(target == null); // Falseと表示される
        Debug.Log(ReferenceEquals(target, null)); // Falseと表示される
        DestroyImmediate(target);
        Debug.Log(target == null); // Trueと表示される
        Debug.Log(ReferenceEquals(target, null)); // Falseと表示される
    }

参考・関連

こちらもどうぞ

関連記事 : Reshaper/Riderの「Possible unintended bypass of lifetime check of underlying Unity engine object」って何ぞや?

RyotaMurohoshi
プログラミングが大好きで、 C#が大好きで、 .NETが大好きで、 LINQが大好きで、 JVM言語が大好きで、 ゲームで遊ぶことが大好きで、 ゲーム開発が大好きで、 頑張るのが大好きで、 Unityが大好きだったから...!
http://mrstar-memo.hatenablog.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away