コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】UnityEngine.Object の Null チェックまとめ

結論

SerializeField で Null なフィールド

  • == null は Null だと判定できる
  • ???.??=is null は UnassignedReferenceException が発生する

Destroy した直後の UnityEngine.Object

  • == null は Null だと判定できない
  • ???.??=is null も Null だと判定できない

Destroy 後に 1 フレーム待った UnityEngine.Object

  • == null は Null だと判定できる
  • ???.??=is null は MissingReferenceException が発生する

Destroy 後に null を代入した UnityEngine.Object

  • == null は Null は判定できる
  • ???.??=is null も Null だと判定できる

引数が呼び出し元で Destroy された場合

  • == null は Null だと判定できる
  • ???.??=is null は MissingReferenceException が発生する

基本的には以下のルールを守れば正確に Null チェックできる

  • UnityEngine.Object に対して ???.??=is null を使用しない
  • Destroy したら変数に null を代入する

目次

検証環境

  • Unity 2020.3.13f1

検証結果

SerializeField で Null なフィールドに対して == null

using UnityEngine;

public class Example : MonoBehaviour
{
    [SerializeField] private Material m_material;

    private void Start()
    {
        Debug.Log( m_material == null ? "null です" : "null ではないです" );
    }
}

「null です」と表示される

SerializeField で Null なフィールドに対して Null 合体演算子(??)

using UnityEngine;

public class Example : MonoBehaviour
{
    [SerializeField] private Material m_material;

    private void Start()
    {
        m_material = m_material ?? new Material( Shader.Find( "Unlit/Texture" ) );
        Debug.Log( m_material.name );
    }
}

「UnassignedReferenceException」が発生する

SerializeField で Null なフィールドに対して Null 条件演算子(?.)

using UnityEngine;

public class Example : MonoBehaviour
{
    [SerializeField] private Material m_material;

    private void Start()
    {
        Debug.Log( m_material?.name );
    }
}

「UnassignedReferenceException」が発生する

SerializeField で Null なフィールドに対して Null 合体代入(??=)

using UnityEngine;

public class Example : MonoBehaviour
{
    [SerializeField] private Material m_material;

    private void Start()
    {
        m_material ??= new Material( Shader.Find( "Unlit/Texture" ) );
        Debug.Log( m_material.name );
    }
}

「UnassignedReferenceException」が発生する

SerializeField で Null なフィールドに対して is null

using UnityEngine;

public class Example : MonoBehaviour
{
    [SerializeField] private Material m_material;

    private void Start()
    {
        Debug.Log( m_material is null ? "null です" : "null ではないです" );
    }
}

「null ではないです」と表示される

Destroy した直後に == null

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );

        Debug.Log( material == null ? "null です" : "null ではないです" );
    }
}

「null ではないです」と表示される

Destroy した直後に Null 合体演算子(??)

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        
        material = material ?? new Material( Shader.Find( "Unlit/Texture" ) );
        Debug.Log( material.name );
    }
}

「Unlit/Texture」ではなく「Unlit/Color」と表示される

Destroy した直後に Null 条件演算子(?.)

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );

        Debug.Log( material?.name );
    }
}

「Unlit/Texture」ではなく「Unlit/Color」と表示される

Destroy した直後に Null 合体代入(??=)

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );

        material ??= new Material( Shader.Find( "Unlit/Texture" ) );
        Debug.Log( material.name );
    }
}

「Unlit/Texture」ではなく「Unlit/Color」と表示される

Destroy した直後に is null

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );

        Debug.Log( material is null ? "null です" : "null ではないです" );
    }
}

「null ではないです」と表示される

Destroy 後に 1 フレーム待って == null

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    private IEnumerator Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        yield return null; // 1 フレーム待つ

        Debug.Log( material == null ? "null です" : "null ではないです" );
    }
}

「null です」と表示される

Destroy 後に 1 フレーム待って Null 合体演算子(??)

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    private IEnumerator Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        yield return null; // 1 フレーム待つ
        
        material = material ?? new Material( Shader.Find( "Unlit/Texture" ) );
        Debug.Log( material.name );
    }
}

MissingReferenceException が発生

Destroy 後に 1 フレーム待って Null 条件演算子(?.)

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    private IEnumerator Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        yield return null; // 1 フレーム待つ

        Debug.Log( material?.name );
    }
}

MissingReferenceException が発生

Destroy 後に 1 フレーム待って Null 合体代入(??=)

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    private IEnumerator Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        yield return null; // 1 フレーム待つ
        
        material ??= new Material( Shader.Find( "Unlit/Texture" ) );
        Debug.Log( material.name );
    }
}

MissingReferenceException が発生

Destroy 後に 1 フレーム待って is null

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    private IEnumerator Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        yield return null; // 1 フレーム待つ

        Debug.Log( material is null ? "null です" : "null ではないです" );
    }
}

「null ではないです」と表示される

Destroy 後に null を代入して == null

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        material = null;

        Debug.Log( material == null ? "null です" : "null ではないです" );
    }
}

「null です」と表示される

Destroy 後に null を代入して Null 合体演算子(??)

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        material = null;

        material = material ?? new Material( Shader.Find( "Unlit/Texture" ) );
        Debug.Log( material.name );
    }
}

「Unlit/Texture」と表示される

Destroy 後に null を代入して Null 条件演算子(?.)

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        material = null;

        Debug.Log( material?.name );
    }
}

「Null」と表示される

Destroy 後に null を代入して Null 合体代入(??=)

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        material = null;

        material ??= new Material( Shader.Find( "Unlit/Texture" ) );
        Debug.Log( material.name );
    }
}

「Unlit/Texture」と表示される

Destroy 後に null を代入して is null

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        Destroy( material );
        material = null;

        Debug.Log( material is null ? "null です" : "null ではないです" );
    }
}

「null です」と表示される

引数が呼び出し元で Destroy されてから == null

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        StartCoroutine( Check( material ) );
        Destroy( material );
    }

    private IEnumerator Check( Material material )
    {
        yield return null; // 1 フレーム待つ
        Debug.Log( material == null ? "null です" : "null ではないです" );
    }
}

「null です」と表示される

引数が呼び出し元で Destroy されてから Null 合体演算子(??)

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        StartCoroutine( Check( material ) );
        Destroy( material );
    }

    private IEnumerator Check( Material material )
    {
        yield return null; // 1 フレーム待つ
        material = material ?? new Material( Shader.Find( "Unlit/Texture" ) );
        Debug.Log( material.name );
    }
}

MissingReferenceException が発生

引数が呼び出し元で Destroy されてから Null 条件演算子(?.)

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        StartCoroutine( Check( material ) );
        Destroy( material );
    }

    private IEnumerator Check( Material material )
    {
        yield return null; // 1 フレーム待つ
        Debug.Log( material?.name );
    }
}

MissingReferenceException が発生

引数が呼び出し元で Destroy されてから Null 合体代入(??=)

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        StartCoroutine( Check( material ) );
        Destroy( material );
    }

    private IEnumerator Check( Material material )
    {
        yield return null; // 1 フレーム待つ
        material ??= new Material( Shader.Find( "Unlit/Texture" ) );
        Debug.Log( material.name );
    }
}

MissingReferenceException が発生

引数が呼び出し元で Destroy されてから is null

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    private void Start()
    {
        var material = new Material( Shader.Find( "Unlit/Color" ) );
        StartCoroutine( Check( material ) );
        Destroy( material );
    }

    private IEnumerator Check( Material material )
    {
        yield return null; // 1 フレーム待つ
        Debug.Log( material is null ? "null です" : "null ではないです" );
    }
}

「null ではないです」と表示される

関連記事