我正在研究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张卡在运行时仍然落到了地面...... 有人可以解释为什么它会被抛出?
答案 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的实例化,如原始代码所示。