はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity】null合体演算子とnull条件演算子についてかるくまとめてみた

この記事でのバージョン
Unity2018.3.9f1

はじめに

今回はnull合体演算子とnull条件演算子の使い方についての記事になります!

前回null許容型についての記事を書いたのですが、そちらと合わせて用いられることも多いようです。

hanaachiru.hatenablog.com

null合体演算子

null合体演算子nullかどうかを判断し処理を分岐させる時に使います。
演算子??と書きます。

using UnityEngine;

public class Hoge : MonoBehaviour
{
    private void Start()
    {
        Rigidbody rb = GetComponent<Rigidbody>() ?? gameObject.AddComponent<Rigidbody>();
    }
}

これは正常に動かない可能性があります(後述)

これはどういう意味かというと、以下のコードと同じ意味になります。

using UnityEngine;

public class Hoge : MonoBehaviour
{
    private void Start()
    {
        Rigidbody rb = GetComponent<Rigidbody>();
        if (rb == null)
            gameObject.AddComponent<Rigidbody>();
    }
}


最初に見た時はやや分かりづらいと感じるかもしれませんが、結構直感的にコードを書くことができるんです。

変数rbgameObjectのRigidbodyコンポーネントの参照を代入しよう
②そういえばRigidbodyコンポーネントがアタッチされていない場合(null)があるかも?
??でその時の対応をしよう

といった感じにコードを書いていくことが可能になります。

null条件演算子

こちらはC#6での機能なので、Edit > Project Settings > Playerから、.NET 4.xを選択しましょう。

f:id:hanaaaaaachiru:20190324212636p:plain

null条件演算子?.を使って書くことができます。

using UnityEngine;

public class Hoge : MonoBehaviour
{
    private void Start()
    {
        Vector3 force = new Vector3(1, 0, 0);
        GetComponent<Rigidbody>()?.AddForce(force);
    }
}

これは正常に動かない可能性があります(後述)

これがどういう意味かと言うと、以下のコードと同じ意味になります。

if(GetComponent<Rigidbody>() != null) GetComponent<Rigidbody>().AddForce(force);

またこの例では用いませんでしたが、返り値をもたせることもできます。

return sale?.Product;

この場合、sale変数がnullでないときは、Prodeuctプロパティの値が返し、nullのときにはnullが返ります

unityで使うときの注意点

ただUnityではNull合体演算子Null条件演算子が正しく動かない可能性があります。
その理由はUnityのオブジェクト(UnityEngine.Objectの派生クラス)はすべて独自nullであるからみたいです。

少し厄介ですがQiitaで拡張メソッドを使ってUnity Objectのnullからいつもの(.NET)のnullへの型変換をする方法を書いてくださっていた方がいました。
少しだけそちらを紹介して終わりにしたいと思います。

UnityのGetCompornent&lt;T&gt;()でNull条件演算子が使えない - Qiita
Unityのnullはnullじゃないかもしれない - Qiita

.NETのnullへキャストする

こちらのスクリプトをunityに追加してください。

public static class ExtensionMethods
{
    public static T NullCast<T>(this T obj) where T : UnityEngine.Object
        => (obj != null) ? obj : null;
}


このコードをざっくり紹介すると、拡張メソッドを用いてオブジェクトが存在するかどうか調べ、存在しない場合は.NETのnullを返しています。

Object.bool - Unity スクリプトリファレンス

実際につかってみましょう。

using UnityEngine;

public class Hoge : MonoBehaviour
{
    private void Start()
    {
        Rigidbody rb = GetComponent<Rigidbody>().NullCast() ?? gameObject.AddComponent<Rigidbody>();
    }
}
using UnityEngine;

public class Hoge : MonoBehaviour
{
    private void Start()
    {
        Vector3 force = new Vector3(1, 0, 0);
        GetComponent<Rigidbody>().NullCast()?.AddForce(force);
    }
}

さいごに

ややunityでnull条件演算子を使うのは厄介でしたが、上手く使っていけたらと思います!

ちなみになんですが、最後の例のような処理をしたい場合は[RequireComponent(typeof(Rigidbody))]をする方が単純かつ最善だと思います。