C# 当索引为(array.length-1)但代码仍然执行时,IndexOutOfRangeException

C# 当索引为(array.length-1)但代码仍然执行时,IndexOutOfRangeException,c#,unity3d,initialization,indexoutofrangeexception,rigid-bodies,C#,Unity3d,Initialization,Indexoutofrangeexception,Rigid Bodies,我正在Unity3d中开发我的第一个程序,在运行时通过实例化对象来测试waters并操纵它们的属性 到目前为止,我的测试场创建了一副垂直展开的卡片,带有不使用重力的刚体组件。然后,它尝试(并成功!)使最高卡片的刚体组件(也是阵列中最后创建的)使用重力 所有这一切都按照计划进行得很好,这些牌以垂直浮动的堆叠形式出现,最高的牌慢慢地将它们全部推到下面的表面。然而,让我困扰的是,将重力分配给那张顶级卡片总是会引发一种索引超常规的异常 public class Deck : MonoBehaviour

我正在Unity3d中开发我的第一个程序,在运行时通过实例化对象来测试waters并操纵它们的属性

到目前为止,我的测试场创建了一副垂直展开的卡片,带有不使用重力的刚体组件。然后,它尝试(并成功!)使最高卡片的刚体组件(也是阵列中最后创建的)使用重力

所有这一切都按照计划进行得很好,这些牌以垂直浮动的堆叠形式出现,最高的牌慢慢地将它们全部推到下面的表面。然而,让我困扰的是,将重力分配给那张顶级卡片总是会引发一种索引超常规的异常

public class Deck : MonoBehaviour {

    private GameController mController;
    public GameObject cardObject;
    public GameObject[] get; 
    public Vector3 position;
    public float rotation;

    void Start () {
        get = new GameObject[52];

        for (int i = 0; i < get.Length; i++) {
            get [i] = Instantiate (cardObject, this.transform) as GameObject;
            GameObject go = get [i];
            Card card = go.GetComponent<Card> ();
            card.SetGameControllerReference (mController);
            card.newCard (i);
            //  public void newCard(int i) {
            //      suit = i / 13;
            //      rank = i % 13;
            //      name = RankString [rank] + " of " + SuitString [suit];
            //  }
            Rigidbody rb = go.GetComponent<Rigidbody> ();
            rb.isKinematic = true;
            MeshRenderer mMeshRenderer = go.GetComponent<MeshRenderer> ();
            mMeshRenderer.enabled = false;
        }
        Materialize (position, rotation);
    }

    public void reset() {
        for (int i = 0; i < get.Length; i++) {
            Destroy (get [i]);
        }
        Start ();
    }

    void SetGameControllerReference (GameController controller) {
        mController = controller;
    }

    public void Materialize (Vector3 pos, float rot) {
        transform.Translate (pos);
        transform.Rotate (0, rot, 0);
        for (int i = 0; i < get.Length; i++) {
            GameObject go = get [i];
            Card card = go.GetComponent<Card> ();
            Material mMaterial = go.GetComponent<MeshRenderer> ().material;
            string path = card.tmString();
            mMaterial.SetTexture ("_MainTex", Resources.Load (path) as Texture);
            Rigidbody rb = go.GetComponent<Rigidbody> ();

            float height = 0.05f + (i * (card.cardWidth));

            Quaternion newQuat = new Quaternion ();
            Vector3 newPos = new Vector3(0, (10 * (i + 1)), 0);
            newQuat.SetLookRotation (newPos, Vector3.up);
            newPos.Set (0, (i + height), 0);

            rb.transform.SetPositionAndRotation (newPos, newQuat);
            rb.useGravity = false;
            rb.isKinematic = false;
            go.GetComponent<MeshRenderer> ().enabled = true;
        }
        // This line ALWAYS throws an IndexOutOfRange Exception.
        get [get.Length - 1].GetComponent<Rigidbody> ().useGravity = true;
    }

    void Update () {}
}
更让我困惑的是,这行代码总是抛出异常。我知道卡片组是52张卡片,我将其硬编码为长度52(我知道这是一种糟糕的做法,但它使卡片数据实例化变得轻而易举),因此我尝试了以下方法:

get[10].getComponent<RigidBody>().useGravity = true;
get[10].getComponent().useGravity=true;

尽管堆栈中的第十一张卡在运行时仍然掉到了地上,但仍然抛出了一个索引自动失效异常…有人能解释为什么会抛出它吗?

而我认为我的数组硬编码为长度52:

void Start () {
    get = new GameObject[52];
事实上,我是在硬编码该数组的一个实例,因此使用了新的关键字。通过将数组声明为长度52

public class Deck : MonoBehaviour {

private GameController mController;
public GameObject cardObject;
public readonly GameObject[] get = new GameObject[52];
我可以确保,当甲板本身初始化时,它将始终初始化为该大小。简单的新手错误,但我真的很感谢大家的帮助

编辑:

更重要的是,我误用了Unity Start()函数,即使在正确声明数组之后也是如此。卡片的实例化应该在Awake()函数中完成。使代码看起来像:

public class Deck : MonoBehaviour {

private GameController mController;
public GameObject cardObject;
public readonly GameObject[] get = new GameObject[52];
public Vector3 position;
public float rotation;

void Start () {

}

void Awake() {
    for (int i = 0; i < get.Length; i++) {
        get [i] = Instantiate (cardObject, this.transform) as GameObject;
        GameObject go = get [i];
        ...
公共类组:单一行为{
私人游戏控制器;
公共游戏对象;
公共只读游戏对象[]获取=新游戏对象[52];
公共向量3位置;
公众浮动轮换;
无效开始(){
}
无效唤醒(){
for(int i=0;i

然后,游戏控制器可以在其Start()中执行甲板的实例化函数,如原始代码中所示。

array.Length-1--当数组为空时,将抛出超出范围异常。as:array.Length=0,您正试图访问0-1=>-1thIndex@PrateekShrivastava正如我提到的,数组被硬编码为长度52;不,不是。它是在start方法中初始化的。它的长度是不确定的。我已将unity设置为在出现错误时暂停,因此它总是在第一帧暂停(因为所讨论的行在start()函数中)但即使到那时,我也可以看到数组读取长度52。我甚至可以检查行编辑的卡片,并且它已经更改了刚体组件事件。如果您在
Start()
初始化数组(您有多确定,此方法首先调用/根本调用?)无论如何,为什么不这样声明它,这样它就可以保证在类的安装时运行。例如:
public GameObject[]get=new GameObject[52];
。更好的是,将它公开为只读GameObject[],这样它就不能从外部重新设计。(每个单独的索引/项目仍然可以分配。)
public class Deck : MonoBehaviour {

private GameController mController;
public GameObject cardObject;
public readonly GameObject[] get = new GameObject[52];
public Vector3 position;
public float rotation;

void Start () {

}

void Awake() {
    for (int i = 0; i < get.Length; i++) {
        get [i] = Instantiate (cardObject, this.transform) as GameObject;
        GameObject go = get [i];
        ...