Menu
CoddyTech

UnityのNull

CoddyのUnityジャーニー「Unityスクリプティングの基礎」セクションの一部。レッスン 46/67。

Unityのオブジェクトには2つの側面があります。スクリプトが保持するC#オブジェクトと、その背後にあるエンジンオブジェクトです。Destroy(obj)はフレームの終わりにエンジン側を削除しますが、変数は依然としてC#側を指しているため、通常のC#の観点ではnullではありません。Unityはこれに対応するために==をオーバーライドしています。オブジェクトが破棄されると、obj == nullはtrueになり、短い判定の!objもtrueになります。これがUnityの偽のnullです。

?.、??、is nullは、その==を使用しません。これらはC#の参照をテストしますが、その参照はまだ存在するため、呼び出しは実行され、破棄されたオブジェクトにアクセスするとMissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it.がスローされます。このラベルには、ノックアウト(破棄)されることがあるレースの先頭を走る者の名前が表示されます。

[SerializeField] private Transform leader;

void Update()
{
    // leader が破棄されると例外が発生する: string shown = leader?.name ?? "nobody";
    string shown = leader != null ? leader.name : "nobody";
    Debug.Log("Leader: " + shown);
}

UnityEngine.Objectに由来するもの(GameObjects、コンポーネント、自分のスクリプト)には、== null、!= null、またはif (obj)で判定し、文字列などの通常のC#オブジェクトには?.と??を使いましょう。また、Destroyはフレームの終わりまで待機することも覚えておきましょう。それまではオブジェクトはまだ生きており、== nullはfalseです。

challenge icon

チャレンジ

中級

ドローンはターゲットを追跡しますが、ゲーム開始から2秒後にターゲットは破棄されます。その後、ConsoleにMissingReferenceExceptionが表示され続けます。これは、target?.positionではターゲットが消えたことを検知できないためです。

Unity独自のnull判定を使ってUpdate()を修正しましょう。ターゲットが存在する間は、ドローンはspeedでターゲットに向かって飛びます。ターゲットが破棄された後は、エラーを出さず、その場にとどまります。

Playを押してConsoleを確認し、スクリプトを修正してからCheckを押しましょう。

自分で試してみよう

using UnityEngine;

public class Chaser : MonoBehaviour
{
    [SerializeField] private Transform target;
    [SerializeField] private float speed = 2f;

    void Start()
    {
        Destroy(target.gameObject, 2f);   // targetは2秒後に破棄される
    }

    void Update()
    {
        Vector3 goal = target?.position ?? transform.position;
        transform.position = Vector3.MoveTowards(transform.position, goal, speed * Time.deltaTime);
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

Unityスクリプティングの基礎のすべてのレッスン