IndexOutOfRangeException, когда index равен ( array.length - 1), но код все еще выполняется

Я работаю над своей первой программой на 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 () {}
}

Палуба создается здесь:

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

    }
}

Что меня еще больше озадачивает, так это то, что строка ВСЕГДА вызывает исключение. Я знаю, что колода состоит из 52 карт, я жестко запрограммировал ее на длину 52 (я знаю, что это плохая практика, но это делает создание данных карт проще простого), поэтому я попробовал следующее:

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

Который все еще выбрасывал исключение IndexOutOfRange, хотя одиннадцатая карта в стеке все еще падала на землю при запуске... Кто-нибудь может объяснить, почему это происходит?

1 ответ

Хотя я полагал, что мой массив был жестко запрограммирован на длину 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];
        ...

Создание экземпляра колоды может быть затем выполнено GameController в его функции Start(), как видно из исходного кода.

Другие вопросы по тегам