当index为(array.length - 1)时,IndexOutOfRangeException,但代码仍然执行

时间:2018-04-16 09:32:12

标签: c# unity3d initialization indexoutofrangeexception rigid-bodies

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

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

所有这些按计划工作都很好,卡片出现在垂直浮动堆叠中,最高的卡片慢慢地将它们全部推到下面的表面。然而,困扰我的部分是将重力分配给顶部卡片总是抛出IndexOutOfRangeException。

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 () {}
}

Deck在这里实例化:

public class GameController : MonoBehaviour {

    public Deck deckObject;
    public Deck deck;


    public string state;

    void Start () {
        state = "Entry";
        deck = Instantiate (deckObject);
        deck.Materialize(new Vector3(10, 10, 0), 45);
    }

    public void reset() {
        deck.reset ();
        state = "Entry";
    }

    public void explode() {
        state = "Explode";
    }

    public void gravityGun() {
        state = "GravityGun";
    }

    void Update () {

    }
}

令我更加困惑的是,ALWAYS行抛出异常。我知道甲板上有52张牌,我把它硬编码为长度为52(糟糕的做法,我知道,但它使卡片数据实例化变得轻而易举),所以我尝试了以下内容:

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

仍然引发了 IndexOutOfRange异常,即使堆栈中的第11张卡在运行时仍然落到了地面...... 有人可以解释为什么它会被抛出?

1 个答案:

答案 0 :(得分:2)

虽然我相信我的阵列被硬编码为长度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];
        ...

然后可以通过它的 Start()函数中的GameController执行Deck的实例化,如原始代码所示。