C# 当索引为(array.length-1)但代码仍然执行时,IndexOutOfRangeException
我正在Unity3d中开发我的第一个程序,在运行时通过实例化对象来测试waters并操纵它们的属性 到目前为止,我的测试场创建了一副垂直展开的卡片,带有不使用重力的刚体组件。然后,它尝试(并成功!)使最高卡片的刚体组件(也是阵列中最后创建的)使用重力 所有这一切都按照计划进行得很好,这些牌以垂直浮动的堆叠形式出现,最高的牌慢慢地将它们全部推到下面的表面。然而,让我困扰的是,将重力分配给那张顶级卡片总是会引发一种索引超常规的异常C# 当索引为(array.length-1)但代码仍然执行时,IndexOutOfRangeException,c#,unity3d,initialization,indexoutofrangeexception,rigid-bodies,C#,Unity3d,Initialization,Indexoutofrangeexception,Rigid Bodies,我正在Unity3d中开发我的第一个程序,在运行时通过实例化对象来测试waters并操纵它们的属性 到目前为止,我的测试场创建了一副垂直展开的卡片,带有不使用重力的刚体组件。然后,它尝试(并成功!)使最高卡片的刚体组件(也是阵列中最后创建的)使用重力 所有这一切都按照计划进行得很好,这些牌以垂直浮动的堆叠形式出现,最高的牌慢慢地将它们全部推到下面的表面。然而,让我困扰的是,将重力分配给那张顶级卡片总是会引发一种索引超常规的异常 public class Deck : MonoBehaviour
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 () {}
}
更让我困惑的是,这行代码总是抛出异常。我知道卡片组是52张卡片,我将其硬编码为长度52(我知道这是一种糟糕的做法,但它使卡片数据实例化变得轻而易举),因此我尝试了以下方法:
get[10].getComponent<RigidBody>().useGravity = true;
get[10].getComponent().useGravity=true;
尽管堆栈中的第十一张卡在运行时仍然掉到了地上,但仍然抛出了一个索引自动失效异常…有人能解释为什么会抛出它吗?而我认为我的数组硬编码为长度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];
...
公共类组:单一行为{
私人游戏控制器;
公共游戏对象;
公共只读游戏对象[]获取=新游戏对象[52];
公共向量3位置;
公众浮动轮换;
无效开始(){
}
无效唤醒(){
for(int i=0;i
然后,游戏控制器可以在其Start()中执行甲板的实例化函数,如原始代码中所示。array.Length-1--当数组为空时,将抛出超出范围异常。as:array.Length=0,您正试图访问0-1=>-1thIndex@PrateekShrivastava正如我提到的,数组被硬编码为长度52;不,不是。它是在start方法中初始化的。它的长度是不确定的。我已将unity设置为在出现错误时暂停,因此它总是在第一帧暂停(因为所讨论的行在start()函数中)但即使到那时,我也可以看到数组读取长度52。我甚至可以检查行编辑的卡片,并且它已经更改了刚体组件事件。如果您在
Start()
初始化数组(您有多确定,此方法首先调用/根本调用?)无论如何,为什么不这样声明它,这样它就可以保证在类的安装时运行。例如:public GameObject[]get=new GameObject[52];
。更好的是,将它公开为只读GameObject[],这样它就不能从外部重新设计。(每个单独的索引/项目仍然可以分配。)
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];
...