search
LoginSignup
6

More than 1 year has passed since last update.

posted at

updated at

UnityのGetCompornent<T>()でNull条件演算子が使えない

2018.3でC#6が昇格(?)して、便利になりました。

しかし

var r = GetComponent<Rigidbody>();
if(r != null)
{
    // Rigidbodyがアタッチされていないとここは通れらない
    r.AddForce(force, mode);
}

// 一方で・・・

GetComponent<Rigidbody>()?.AddForce(force, mode);
// MissingComponentException発生!

ゲームオブジェクトに type がアタッチされている場合は type のタイプを使用してコンポーネントを返します。ない場合は null です
https://docs.unity3d.com/ja/current/ScriptReference/Component.GetComponent.html

なんでやねん!

どうもGetComponent<T>()で帰ってくるnullは真正のnullではないみたいです。デバッカで見ると{null}となっています。
発生している例外もNullRefarenceExceptionではありません。

C# 6で導入されたnull条件演算子(?.)ですが、以下の2つの式がほぼ同じ意味になります。
x != null ? x.M() : null
x ?.M()
「ほぼ」であって「完全に同じ」と言えないのは、==演算子を呼ぶか呼ばないかが変わってしまうせいです。 前者(自分で==を呼んでいるやつ)はオーバーロードされた==を呼び出しますが、 後者(?.を利用)は呼びません(直接nullかどうか調べます)。
https://ufcpp.net/blog/2016/12/tipsnulloperation/

==がオーバロードされています。

(追記)どうしてもnull条件演算子が使いたい!!

UnityObject版null -> 正真正銘のnullに変換する操作を拡張メソッドで隠蔽する方法があるそうです。

本来のnull条件演算子だけに比べると少し長くなってしまいますが、それでもif(component!=null)で囲むよりは幾分か短く書くことが出来ます。

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

GetComponent<Rigidbody>().NullCast()?.AddForce(force, mode); // 推論が効くはず

詳細は@albireoさんのコメントを参照。(ありがとうございました!🙇🙇🙇)

(追記)参考、この辺に詳しい話が書かれてますね

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
6