読者です 読者をやめる 読者になる 読者になる

テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

AddComponentに気をつけろ!

Unity トラブルシューティング スクリプト

UnityのGameObjectコンテナを使う面白い使い方として、AddComponentがある。この機能は、GameObjectに特定のコンポーネントを追加し、その参照を得る物だ。これを使うと、オブジェクトに動的に機能を追加する事が出来る。

しかし、このAddComponentを利用する上で、一点注意するべき事がある。それは、コンポーネントがオブジェクトを初期化していない場合、null reference exception が発生するケースが有ることだ。


例えば以下のようなコンポーネントがあったとする。

using UnityEngine;
using System.Collections;

public class ComponentTest : MonoBehaviour 
{
    public DataClass datac;

    void Start()
    {
        Debug.Log(datac.count);
    }

    [System.Serializable]
    public class DataClass
    {
        public int count = 100;
        public string msg = "super man";
    }
}

スクリーンショット 2014-05-31 18.57.36
コンポーネントをマニュアルでアタッチした場合、このStartイベント内に記述したDebug.Logの引数は100となる。これは何時もの使い方だ。しかし、コンポーネントをAddComponentから追加した場合、StartイベントのDebug.Logは Null reference exceptionを返してしまう。

ここで問題となるのが、datacを生成するタイミングについてだ。どうも確認した限り、Inspectorで表示されると生成されるらしい。そのためコンポーネントをマニュアルで登録した場合は発生しないが、AddComponentから生成した場合は発生するということだ。

ちなみにクラスなら発生するので、例えばstring等でも発生する。



対策は非常に簡単だ。Unityのシリアライズでに頼らず、自身でインスタンス化してしまえば良い。つまり、こういう事だ。もしくはnullチェックを噛ましても良い。

using UnityEngine;
using System.Collections;

public class ComponentTest : MonoBehaviour 
{
    public DataClass datac = new DataClass();

    void Start()
    {
        Debug.Log(datac.count);
    }

    [System.Serializable]
    public class DataClass
    {
        public int count = 100;
        public string msg = "super man";
    }
}

もう一つ、structを使う手もある。structはnullを許容しないのでこのように記述してもnullreferenceexceptionが発生する事は無い。ただしスタック領域に生成されるので使いすぎには注意が必要だ。