Unity游戏ArgumentOutOfRangeException异常排查求助
解决Unity中设置菜单外星人名称时的
ArgumentOutOfRangeException异常 我来帮你排查这个问题,这个异常的核心原因是列表索引越界,咱们一步步拆解分析:
异常根源分析
先看你的菜单赋值代码里的循环:
for (int buttonIndex = monsterButtons.Count; buttonIndex > 0; buttonIndex--) { monsterButtons [buttonIndex].GetComponentInChildren<Text> ().text = BestiariumData.scannedSpecies [buttonIndex].name; }
这里有两个明显的问题:
- 循环起始索引错误:List的索引是从
0开始的,最大有效索引是Count - 1。你用monsterButtons.Count作为起始值,比如按钮列表有3个元素,Count是3,直接访问monsterButtons[3]就会超出范围。 - 未校验两个列表的数量匹配:
scannedSpecies的元素数量可能少于monsterButtons的数量,当buttonIndex超过scannedSpecies.Count - 1时,访问scannedSpecies[buttonIndex]也会触发越界异常。
另外,你的BestiariumData里用单独的dnaBar_1到dnaBar_8来存储进度,这种写法不仅冗余,还很容易和scannedSpecies的元素对应不上,进一步加剧索引问题。
解决方案
1. 修复菜单赋值的循环逻辑
把循环改成从0开始遍历,同时增加索引有效性校验,避免越界:
public List<GameObject> monsterButtons = new List<GameObject>(); public static bool nameButtons = false; void LateUpdate () { if (nameButtons) { // 正向遍历按钮列表,索引从0到Count-1 for (int buttonIndex = 0; buttonIndex < monsterButtons.Count; buttonIndex++) { Text buttonText = monsterButtons[buttonIndex].GetComponentInChildren<Text>(); // 先检查scannedSpecies是否有对应索引的元素 if (buttonIndex < BestiariumData.scannedSpecies.Count) { buttonText.text = BestiariumData.scannedSpecies[buttonIndex].name; // 如果要显示DNA进度,可以同步取对应的savedDNAFillRates值 // 比如:buttonProgress.fillAmount = BestiariumData.savedDNAFillRates[buttonIndex]; } else { // 没有对应扫描物种时显示默认文本 buttonText.text = "未扫描"; } } } }
2. 优化BestiariumData的数据结构
把单独的dnaBar_1到dnaBar_8替换成与scannedSpecies对应的列表,这样每个扫描的物种都有对应的DNA进度,避免索引混乱:
public static List<GameObject> scannedSpecies = new List<GameObject>(); public static List<float> savedDNAFillRates = new List<float>(); // 删除原来的dnaBar_1到dnaBar_8字段
3. 修正射线扫描的存储逻辑
在扫描完成添加物种时,同步把DNA进度加入savedDNAFillRates,后续更新进度时也通过索引对应:
else if (dna_percent_0_to_1 >= 1) { EnemyAI enemyAI = hitInfo.collider.gameObject.GetComponent<EnemyAI>(); if (enemyAI.raceIndex == 1) { if (!raceOneWasAdded) { BestiariumData.scannedSpecies.Add(hitInfo.collider.gameObject); // 添加初始DNA进度(你原来的0.25f) BestiariumData.savedDNAFillRates.Add(0.25f); raceOneWasAdded = true; } else { // 找到对应物种的索引,更新进度 int targetIndex = BestiariumData.scannedSpecies.FindIndex(obj => obj.GetComponent<EnemyAI>().raceIndex == 1); if (targetIndex != -1) { BestiariumData.savedDNAFillRates[targetIndex] += 0.25f; // 确保进度不超过100% BestiariumData.savedDNAFillRates[targetIndex] = Mathf.Min(BestiariumData.savedDNAFillRates[targetIndex], 1f); } } } // 重置扫描进度 dna_percent_0_to_1 = 0f; dna_collect_circle.fillAmount = 0f; enemyAI.dna_collected = true; }
额外建议
- 尽量用
foreach遍历列表(如果不需要索引的话),可以减少手动处理索引的错误。 - 对List的访问操作,最好都加上
if (index >=0 && index < list.Count)的校验,尤其是在动态添加/删除元素的场景下。
内容的提问来源于stack exchange,提问作者M_NEN
相关产品推荐
相关产品推荐

