I'm working on my first program in Unity3d, testing the waters with instantiating objects at runtime and manipulating their properties.
So far my testing ground creates a deck of cards spread out vertically, with RigidBody component that do not use gravity. It then attempts (and succeeds!) to make the RigidBody component of the highest card (which is also the last created in the array) use gravity.
All of this works according to plan just fine, the cards appear in a vertical floating stack, and the highest card slowly pushes them all down to the surface below. The part that bothers me however is that assigning gravity to that top card always throws an 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 () {}
}
The Deck is instantiated here:
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 () {
}
}
What perplexes me even more is that the line ALWAYS throws the exception. I know that the deck is 52 cards, I hardcoded it to be length 52 (bad practice, I know, but it makes card data instantiation a breeze), and so I tried the following:
get[10].getComponent<RigidBody>().useGravity = true;
Which still threw an IndexOutOfRange exception, even though the eleventh card in the stack still fell down to the ground upon running... Can somebody explain why it's getting thrown?