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(), как видно из исходного кода.