DestroyされたComponentはinterface越しにnullチェックできない
Componentをinterfaceを使って扱っていたら困った話。困った原因を端的に表すコードが以下のようなものです。
using System.Collections; using UnityEngine; public class Root : MonoBehaviour { [SerializeField] Test test; IEnumerator Start() { ITest itf = test; Destroy(test.gameObject); yield return null; Debug.Log($"Component: {test} {test == null}"); Debug.Log($"Interface: {itf} {itf == null}"); } } public class Test : MonoBehaviour, ITest { } public interface ITest { }
これを実行すると
Component: null True Interface: null False
interface側は、ToStringするとnullと出るのに、==nullによるチェックではFalseと出る、という不思議な状況です。自分はこの現象により意図しない挙動になって困りました。「ComponentがDestroyされたらある処理を実行しよう」とそのComponentをInterface型変数に収めてnullチェックして待っていたのですが、いつまで経ってもTrueにならず空振りに終わりました。
とりあえずの対策はinterfaceにnullチェック関数を持たせることです。
using UnityEngine; public class Test : MonoBehaviour, ITest { bool ITest.IsNullComponent => this == null; } public interface ITest { bool IsNullComponent { get; } }
あまり上手い解決方法ではないので、もっと良い方法は無いかな、と思います。