Unity开发游戏触发ArgumentOutOfRangeException异常求助
Unity开发中的索引越界异常问题
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <00000000000000000000000000000000>:0)
GameController.Update () (at Assets/Scripts/GameController.cs:95)
项目存在多个错误,但唯有此异常导致项目完全无法运行,异常位于第95行。
完整代码
using UnityEngine; using UnityEngine.UI; using System; using System.Collections; using System.Collections.Generic; using UnityEngine.EventSystems; public class GameController : MonoBehaviour { private CubePos nowCube = new CubePos(0, 1, 0); public float cubeChangePlaceSpeed = 0.5f; public Transform cubeToPlace; private float camMoveToYPosition, camMoveSpeed = 2f; public Text scoreTxt; public GameObject[] cubesToCreate; public GameObject allCubes, vfx; public GameObject[] canvasStartPage; private Rigidbody allCubesRb; public Color[] bgColors; private Color toCameraColor; private bool IsLose, firstCube; private List<Vector3> allCubesPositions = new List<Vector3> { new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(-1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, -1), new Vector3(1, 0, 1), new Vector3(-1, 0, -1), new Vector3(-1, 0, 1), new Vector3(1, 0, -1), }; private int prevCountMaxHorizontal = 0; private Transform mainCam; private Coroutine showCubePlace; private List<GameObject> posibleCubesToCreate = new List<GameObject>(); private void Start() { if (PlayerPrefs.GetInt("score") < 5) posibleCubesToCreate.Add(cubesToCreate[0]); else if(PlayerPrefs.GetInt("score") < 10) AddPossibleCubes(2); else if (PlayerPrefs.GetInt("score") < 15) AddPossibleCubes(3); else if (PlayerPrefs.GetInt("score") < 25) AddPossibleCubes(4); else if (PlayerPrefs.GetInt("score") < 35) AddPossibleCubes(5); else if (PlayerPrefs.GetInt("score") < 50) AddPossibleCubes(6); else if (PlayerPrefs.GetInt("score") < 75) AddPossibleCubes(7); else if (PlayerPrefs.GetInt("score") < 100) AddPossibleCubes(8); scoreTxt.text = "<size=47><color=#d58508>best:</color></size> " + PlayerPrefs.GetInt("score") + " <size=33>now:</size> "; toCameraColor = Camera.main.backgroundColor; mainCam = Camera.main.transform; camMoveToYPosition = 5.9f + nowCube.y - 1f; allCubesRb = allCubes.GetComponent<Rigidbody>(); showCubePlace = StartCoroutine(ShowCubePlace()); } private void Update() { if((Input.GetMouseButtonDown(0) || Input.touchCount > 0) && cubeToPlace != null && allCubes != null && !EventSystem.current.IsPointerOverGameObject()) { #if !UNITY_EDITOR if (Input.GetTouch(0).phase != TouchPhase.Began) return; #endif if(!firstCube) { firstCube = true; foreach (GameObject obj in canvasStartPage) Destroy(obj); } GameObject createCube = null; if (posibleCubesToCreate.Count == 1) createCube = posibleCubesToCreate[0]; else createCube = posibleCubesToCreate[UnityEngine.Random.Range(0, posibleCubesToCreate.Count)]; GameObject newCube = Instantiate( createCube, cubeToPlace.position, Quaternion.identity) as GameObject; newCube.transform.SetParent(allCubes.transform); nowCube.setVector(cubeToPlace.position); allCubesPositions.Add(nowCube.getVector()); if (PlayerPrefs.GetString("music") != "No") GetComponent<AudioSource>().Play(); GameObject newVfx = Instantiate(vfx, newCube.transform.position, Quaternion.identity) as GameObject; Destroy(newVfx, 1.5f); allCubesRb.isKinematic = true; allCubesRb.isKinematic = false; SpawnPositions(); MoveCameraChangeBg(); } //无法使用该代码(游戏失败后删除主立方体) /* if (!IsLose && allCubesRb.velocity.magnitude < 0.1f) { Destroy(cubeToPlace.gameObject); IsLose = true; StopCoroutine(showCubePlace); } */ mainCam.localPosition = Vector3.MoveTowards(mainCam.localPosition, new Vector3(mainCam.localPosition.x, camMoveToYPosition, mainCam.localPosition.z), camMoveSpeed * Time.deltaTime); if (Camera.main.backgroundColor != toCameraColor) Camera.main.backgroundColor = Color.Lerp(Camera.main.backgroundColor, toCameraColor, Time.deltaTime / 1.5f); } IEnumerator ShowCubePlace() { while(true) { SpawnPositions(); yield return new WaitForSeconds(cubeChangePlaceSpeed); } } private void SpawnPositions() { List<Vector3> positions = new List<Vector3>(); if (IsPositionEmpty(new Vector3(nowCube.x + 1, nowCube.y, nowCube.z)) && nowCube.x + 1 != cubeToPlace.position.x) positions.Add(new Vector3(nowCube.x + 1, nowCube.y, nowCube.z)); if (IsPositionEmpty(new Vector3(nowCube.x - 1, nowCube.y, nowCube.z)) && nowCube.x - 1 != cubeToPlace.position.x) positions.Add(new Vector3(nowCube.x - 1, nowCube.y, nowCube.z)); if (IsPositionEmpty(new Vector3(nowCube.x, nowCube.y + 1, nowCube.z)) && nowCube.y + 1 != cubeToPlace.position.y) positions.Add(new Vector3(nowCube.x, nowCube.y + 1, nowCube.z)); if (IsPositionEmpty(new Vector3(nowCube.x, nowCube.y - 1, nowCube.z)) && nowCube.y - 1 != cubeToPlace.position.y) positions.Add(new Vector3(nowCube.x, nowCube.y - 1, nowCube.z)); if (IsPositionEmpty(new Vector3(nowCube.x, nowCube.y, nowCube.z + 1)) && nowCube.z + 1 != cubeToPlace.position.z) positions.Add(new Vector3(nowCube.x, nowCube.y, nowCube.z + 1)); if (IsPositionEmpty(new Vector3(nowCube.x, nowCube.y, nowCube.z - 1)) && nowCube.z - 1 != cubeToPlace.position.z) positions.Add(new Vector3(nowCube.x, nowCube.y, nowCube.z - 1)); if (positions.Count > 1) cubeToPlace.position = positions[UnityEngine.Random.Range(0, positions.Count)]; else if (positions.Count == 0) IsLose = true; else cubeToPlace.position = positions[0]; } private bool IsPositionEmpty(Vector3 targetPos) { if (targetPos.y == 0) return false; foreach(Vector3 pos in allCubesPositions) { if (pos.x == targetPos.x && pos.y == targetPos.y && pos.z == targetPos.z) return false; } return true; } private void MoveCameraChangeBg() { int maxX = 0, maxY = 0, maxZ = 0, maxHor; foreach(Vector3 pos in allCubesPositions) { if (Mathf.Abs(Convert.ToInt32(pos.x)) > maxX) maxX = Convert.ToInt32(pos.x); if (Convert.ToInt32(pos.y) > maxY) maxY = Convert.ToInt32(pos.y); if (Mathf.Abs(Convert.ToInt32(pos.z)) > maxZ) maxZ = Convert.ToInt32(pos.z); } // 记录分数代码 27.02.23 maxY--; if (PlayerPrefs.GetInt("score") < maxY) PlayerPrefs.SetInt("score", maxY); scoreTxt.text = "<size=47><color=#d58508>best:</color></size> " + PlayerPrefs.GetInt("score") + " <size=33>now:</size> " + maxY; camMoveToYPosition = 5.9f + nowCube.y - 1f; maxHor = maxX > maxZ ? maxX : maxZ; if(maxHor % 3 == 0 && prevCountMaxHorizontal != maxHor) { mainCam.localPosition -= new Vector3(0, 0, 2.5f); prevCountMaxHorizontal = maxHor; } if (maxY >= 7) toCameraColor = bgColors[2]; else if (maxY >= 5) toCameraColor = bgColors[1]; else if (maxY >= 2) toCameraColor = bgColors[0]; } private void AddPossibleCubes(int till) { for(int i = 0; i < till; i++) posibleCubesToCreate.Add(cubesToCreate[i]); } } struct CubePos { public int x, y, z; public CubePos(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } public Vector3 getVector() { return new Vector3(x, y, z); } public void setVector(Vector3 pos) { x = Convert.ToInt32(pos.x); y = Convert.ToInt32(pos.y); z = Convert.ToInt32(pos.z); } }
问题原因
posibleCubesToCreate列表为空:当玩家分数≥100时,Start()方法中无对应分支处理,列表未添加任何元素,后续Update()中直接访问索引触发越界。- 缺失空值校验:获取
createCube时未检查列表是否为空,直接通过索引访问。 - 数组越界风险:
AddPossibleCubes()方法中till参数可能超过cubesToCreate数组实际长度,导致添加元素时越界。
修复方案
1. 补充分数≥100的分支
修改Start()方法,添加兜底逻辑:
private void Start() { if (PlayerPrefs.GetInt("score") < 5) posibleCubesToCreate.Add(cubesToCreate[0]); else if(PlayerPrefs.GetInt("score") < 10) AddPossibleCubes(2); else if (PlayerPrefs.GetInt("score") < 15) AddPossibleCubes(3); else if (PlayerPrefs.GetInt("score") < 25) AddPossibleCubes(4); else if (PlayerPrefs.GetInt("score") < 35) AddPossibleCubes(5); else if (PlayerPrefs.GetInt("score") < 50) AddPossibleCubes(6); else if (PlayerPrefs.GetInt("score") < 75) AddPossibleCubes(7); else if (PlayerPrefs.GetInt("score") < 100) AddPossibleCubes(8); else // 分数≥100时添加所有可用预制体 AddPossibleCubes(cubesToCreate.Length); // 原后续代码... }
2. 添加空列表校验
修改Update()中获取createCube的逻辑:
GameObject createCube = null; if (posibleCubesToCreate.Count == 0) { if(cubesToCreate.Length > 0) createCube = cubesToCreate[0]; else { Debug.LogError("请在Inspector面板中为cubesToCreate数组赋值!"); return; } } else if (posibleCubesToCreate.Count == 1) createCube = posibleCubesToCreate[0]; else createCube = posibleCubesToCreate[UnityEngine.Random.Range(0, posibleCubesToCreate.Count)];
3. 修复AddPossibleCubes()方法
添加数组长度校验:
private void AddPossibleCubes(int till) { // 取till和数组长度的最小值,防止越界 int maxIndex = Mathf.Min(till, cubesToCreate.Length); for(int i = 0; i < maxIndex; i++) posibleCubesToCreate.Add(cubesToCreate[i]); }
4. 额外检查
确保Unity Inspector面板中cubesToCreate数组已正确添加预制体,无空元素。
内容的提问来源于stack exchange,提问作者way1t
相关产品推荐
相关产品推荐

