76106


class型の多次元配列またはジャグ配列のインスタンスを参照しようとすると

[code]

    NullReferenceException
    
[/code]

というエラーが出ます。

[code]

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Class0 : MonoBehaviour
    {
        public class a
        {
            public int b;
        }
        public a[,] a = new a[5,5];
    
        void Start()
        {
            Debug.Log(a[0,0].b);
        }
    }
    
[/code]

そこで

[code]

    Debug.Log(a[0,0]);
    
[/code]

を実行してみると

[code]

    Null
    
[/code]

とでました。  
多次元配列やジャグ配列ではなくただのclass型の変数や配列で試したところ、エラーやNullが出なくなりました。  
class型の変数は多次元配列やジャグ配列にできないのでしょうか、もし入れる方法があるならば教えてもらいたいです。  
どうぞよろしくお願いします。


CC BY-SA 4.0
2021-05-27T05:48:24.867
76104
2021-05-27T07:11:51.217
2021-05-27T06:52:38.877
45521
45521
question
c# unity3d array
Unityでclass型の多次元配列・ジャグ配列のインスタンスを参照しようとするとエラーが出ます


それがC#の仕様のようですね。  
配列としてのサイズは指定されているけれども、個々の要素は初期化(new)されて無いということでしょう。

古い記事ですが、ちょうど同様にUnity C#での使い方を模索していた結果が記述されています。  
[C#でクラスのインスタンスが初期化されてない](https://qiita.com/scnsh/items/8eb80000267ac99d2bf4)

> これは、配列を初期化した場合に各要素に対してコンストラクタが呼び出されないことが原因です。  
>  ただサイズを確保してくれるだけなので、以下のように変更して、確実にコンストラクタを呼ぶようにします。

例外で止まった時点でデバッガで配列の中身を見ると、全部`null`になっていました。

明示的に各要素を初期化(new)する処理が必要ということですね。

他にはこんな記事も。  
[C# クラス型配列変数の初期化について](https://ja.stackoverflow.com/q/41333/26370)  
[クラス配列の初期化](https://teratail.com/questions/71423)

* * *

追記：

コンストラクタが使われていないのがちょっと気になったので追っていたらこんな記事があるんですね。  
[MonoBehaviourのコンストラクタ/デストラクタ](https://yotiky.hatenablog.com/entry/2018/11/22/MonoBehaviour%E3%81%AE%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF/%E3%83%87%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF)  
[[Unity]コンストラクタが使えない原因を（雑に）まとめました。](https://ameblo.jp/nocafenolife-
blog/entry-12356243159.html)

>   * MonoBehaviourを継承しているクラスでは、コンストラクタを宣言してはいけない（Unity側が困るから）。
>   * フィールドの初期化は”float speed = 20;”のようにして初期化する（変数初期化子による初期化）。
>   * それ以外の初期化的な処理は、Awake関数ないし、Start関数で行う。
>

[【Unity】コンストラクタ使えない問題](http://jyumotendo.jeez.jp/2017/12/15/blog20171215/)

> コンストラクタは使用しない仕様  
>  unityのマニュアルより  
>  初期化時にはAwakeイベントを使用する。初期化用のコンストラクタは定義しない。

上記を併せると、相応しいかどうかは分かりませんが、以下のようにStart()のDebug.Log()でアクセスする前にAwake()で初期化しておくということでしょう。  
(本当にその順番で(しかも1回だけ)動くのか？は不明ですが)

[code]

    void Awake()
    {
        for(int x=0; x < 5; x++)
        {
            for (int y = 0; y < 5; y++)
            {
                a[x, y] = new a();
            }
        }
    }
    
    void Start()
    {
        Debug.Log(a[0,0].b);
    }
    
[/code]


CC BY-SA 4.0
2021-05-27T06:33:46.020
76106
2021-05-27T07:11:51.217
2021-05-27T07:11:51.217
26370
26370
76104
answer