Unity中索引为array.length-1时触发IndexOutOfRangeException但代码仍执行
哈哈,刚上手Unity就碰到数组索引的坑太正常了!我当初第一次写实例化逻辑的时候也栽过一模一样的跟头😅,结合你描述的场景,咱们来一步步排查和解决这个问题:
先搞清楚报错的核心原因
IndexOutOfRangeException本质就是你访问了数组不存在的索引——比如当数组长度为0时,array.length-1等于-1,这肯定超出了数组的合法索引范围(数组索引从0开始);或者数组长度比你预期的小,比如你以为有5张卡牌,但实际数组里只有3张,array[4]自然就不存在了。
可能的触发场景&对应的解决办法
1. 数组长度和实际实例化的卡牌数量不匹配
数组是固定长度的,如果你先声明了一个固定长度的数组,但实例化时的卡牌数量没填满数组,或者实例化数量超过了数组长度,都会出问题。
👉 解决办法:改用List<GameObject>代替数组!List可以动态添加元素,完全适配实例化的动态场景:
// 把数组换成List,支持动态添加 List<GameObject> cardsList = new List<GameObject>(); void Start() { // 实例化卡牌的循环逻辑 for (int i = 0; i < 5; i++) { GameObject newCard = Instantiate(cardPrefab, new Vector3(0, i * 2, 0), Quaternion.identity); Rigidbody rb = newCard.GetComponent<Rigidbody>(); rb.useGravity = false; // 每实例化一张就加入List cardsList.Add(newCard); } // 修改最后一张卡牌的重力前,先判断List不为空 if (cardsList.Count > 0) { GameObject lastCard = cardsList[cardsList.Count - 1]; lastCard.GetComponent<Rigidbody>().useGravity = true; } else { Debug.LogWarning("警告:没有实例化任何卡牌!"); } }
2. 访问数组的时机不对
你可能在卡牌还没完全实例化完成时就去访问数组了——比如如果实例化逻辑放在协程、异步方法里,或者在Awake()里访问但实例化在Start()里,这时候数组还是空的,自然会触发越界错误。
👉 解决办法:确保访问数组的代码在所有卡牌实例化完成后执行:
- 如果用协程,就在协程的末尾处理最后一张卡牌的重力;
- 把修改重力的逻辑放在实例化循环的外面,确保循环执行完再访问。
3. 数组被意外修改
有没有其他地方的代码在修改这个数组?比如不小心重新赋值了数组,或者删除了元素,导致数组长度突然变小,但你还是用原来的逻辑去访问array.length-1。
👉 解决办法:给数组/List加日志调试,在访问前打印长度:
// 访问前先打印数组长度,确认是不是符合预期 Debug.Log($"当前卡牌数组长度:{cardsArray.Length}"); if (cardsArray.Length > 0) { cardsArray[cardsArray.Length - 1].GetComponent<Rigidbody>().useGravity = true; }
为什么代码还能继续执行?
Unity的错误处理机制比较特殊,这种非致命的异常(比如只是访问数组越界但没影响核心逻辑)不会直接让程序崩溃,只会在Console里报错,但后续代码还是会继续跑——不过这可不是好事,得把这个坑填上,不然哪天逻辑复杂了就会出大问题。
内容的提问来源于stack exchange,提问作者Dr_StrangeKill

