Unity如何正确加载图片到类数组并解决索引越界异常
问题根因
两个报错和异常现象来自三处明确的代码逻辑错误:
- 数组越界异常:所有遍历数组的for循环都使用了
i <= 数组长度的判断条件,C#数组索引从0开始计数,最大合法索引值为数组长度 - 1,当循环变量等于数组长度时访问数组,必然触发IndexOutOfRangeException - 非图片字段全为空:图片下载协程
DownloadImage每次拿到单张图片后,都会重新实例化整个DataClassArray数组及内部的所有CollectionDataClass元素,之前在GenerateCollectionData里填充好的name/id/thumbnail字段会被全部清空覆盖 - 仅加载出一张图片:
DownloadImage拿到单张图片后,会把这张图片循环赋值给所有集合项,最终所有项只会保留最后一次下载完成的图片;同时调用协程时传入的count参数没有实际定位作用,没有把图片和对应的集合项做绑定。
修复方案
- 所有数组遍历循环的判断条件从
i <= 数组.Length修改为i < 数组.Length,解决越界问题 - 移除
DownloadImage协程里全量重建数组、遍历所有元素赋值的逻辑,下载完成后直接给对应索引位置的已有元素赋值即可 - 调用
DownloadImage时传入当前元素对应的外层、内层索引,准确定位要赋值图片的集合项,避免全量覆盖。
修正后代码
[System.Serializable] public class CollectionDataClass { public string name; public string id; public string thumbnail; public Texture2D collectionImage; } [System.Serializable] public class DataClass { [SerializeField] public CollectionDataClass[] collectionDataClass; } [SerializeField] private DataClass[] DataClassArray; public IEnumerator BookCatogary(string reqParameter) { BookCatogaryBodyClass BookCatogryClass = new BookCatogaryBodyClass(reqParameter); string json = JsonConvert.SerializeObject(BookCatogryClass); Debug.Log("==========================>" + json); var req = new UnityWebRequest(bookCategaryAPI, "POST"); byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(json); req.uploadHandler = (UploadHandler)new UploadHandlerRaw(jsonToSend); req.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); req.SetRequestHeader("Content-Type", "application/json"); yield return req.SendWebRequest(); if (req.isNetworkError) { Debug.Log("Error While Sending: " + req.error); } else { Debug.Log("Received: " + req.downloadHandler.text); string temp = req.downloadHandler.text; bookCatogaryObject = JsonConvert.DeserializeObject<BookCatogaryReceivedDataClass>(temp); catogaryCount = bookCatogaryObject.Data.Rows.Count; GetCatogariesName(catogaryCount); GenerateCollectionData(); } } public void GenerateCollectionData() { int rowCount = bookCatogaryObject.Data.Rows.Count; DataClassArray = new DataClass[rowCount]; // 修复循环条件:<= 改为 < for (int i = 0; i < rowCount; i++) { DataClassArray[i] = new DataClass(); int itemCount = bookCatogaryObject.Data.Rows[i].String.Count; DataClassArray[i].collectionDataClass = new CollectionDataClass[itemCount]; for (int m = 0; m < itemCount; m++) { DataClassArray[i].collectionDataClass[m] = new CollectionDataClass(); DataClassArray[i].collectionDataClass[m].name = bookCatogaryObject.Data.Rows[i].String[m].CollectionTitle; DataClassArray[i].collectionDataClass[m].id = bookCatogaryObject.Data.Rows[i].String[m].Id; DataClassArray[i].collectionDataClass[m].thumbnail = bookCatogaryObject.Data.Rows[i].String[m].CollectionThumbnail; // 传入当前元素的索引,准确定位赋值位置 StartCoroutine(DownloadImage(DataClassArray[i].collectionDataClass[m].thumbnail, i, m)); } } } // 修改参数,接收外层i、内层m索引 IEnumerator DownloadImage(string mediaUrl, int rowIndex, int itemIndex) { UnityWebRequest request = UnityWebRequestTexture.GetTexture(mediaUrl); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { Debug.Log(request.error); } else { // 直接给对应索引的元素赋值,不重建整个数组 Texture2D loadedTex = ((DownloadHandlerTexture)request.downloadHandler).texture; DataClassArray[rowIndex].collectionDataClass[itemIndex].collectionImage = loadedTex; } }
注意:如果使用的是Unity 2020及以上版本,
isNetworkError、isHttpError已被标记为过时,可替换为result != UnityWebRequest.Result.Success做请求结果判断。
内容的提问来源于stack exchange,提问作者Omkar P
相关产品推荐
相关产品推荐

