I have following code in which I wand to load images. But whenever I Run the code other fields in collection are found empty and only one image is found in all collection data, & The following error is generated. IndexOutOfRangeException: Index was outside the bounds of the array. (wrapper stelemref) System.Object.virt_stelemref_class_small_idepth(intptr,object)
Below is my code :
[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()
{
DataClassArray = new DataClass[bookCatogaryObject.Data.Rows.Count];
for (int i = 0; i <= bookCatogaryObject.Data.Rows.Count; i )
{
DataClassArray[i] = new DataClass();
DataClassArray[i].collectionDataClass = new CollectionDataClass[bookCatogaryObject.Data.Rows[i].String.Count];
for (int m = 0; m < bookCatogaryObject.Data.Rows[i].String.Count; 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(mediaUrl: DataClassArray[i].collectionDataClass[m].thumbnail , bookCatogaryObject.Data.Rows[i].String.Count));
}
}
}
IEnumerator DownloadImage(string mediaUrl, int count)
{
UnityWebRequest request = UnityWebRequestTexture.GetTexture(mediaUrl);
yield return request.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
Debug.Log(request.error);
else
{
//collectionImage = ((DownloadHandlerTexture)request.downloadHandler).texture;
//collectionImageContainer[count] = collectionImage;
for (int i = 0; i <= bookCatogaryObject.Data.Rows.Count; i )
{
DataClassArray[i] = new DataClass();
DataClassArray[i].collectionDataClass = new CollectionDataClass[bookCatogaryObject.Data.Rows[i].String.Count];
for (int m = 0; m < bookCatogaryObject.Data.Rows[i].String.Count; m )
{
DataClassArray[i].collectionDataClass[m] = new CollectionDataClass();
DataClassArray[i].collectionDataClass[m].collectionImage = ((DownloadHandlerTexture)request.downloadHandler).texture;
}
}
}
}
CodePudding user response:
This is not an answer to your question. I just wanted to show you how you can simplify code by using temp locals and object initializers. It also makes the code more efficient because it eliminates repeated indexing and member accesses. But more importantly, it makes the code more readable.
public async void GenerateCollectionData()
{
var rows = bookCatogaryObject.Data.Rows;
DataClassArray = new DataClass[rows.Count];
for (int i = 0; i < rows.Count; i ) {
var currentString = rows[i].String;
var dc = new DataClass {
collectionDataClass = new CollectionDataClass[currentString.Count]
};
DataClassArray[i] = dc;
for (int m = 0; m < currentString.Count; m ) {
var collection = currentString[m];
dc.collectionDataClass[m] = new CollectionDataClass {
name = collection.CollectionTitle,
id = collection.Id,
thumbnail = collection.CollectionThumbnail,
collectionImage = await GetImage(collection.CollectionThumbnail)
};
}
}
}
CodePudding user response:
So finally I found the answer to above question, instead of using coroutines I used async Task to return downloaded texture to GenerateCollectionData() method. Below is code for reference :
public async void GenerateCollectionData()
{
DataClassArray = new DataClass[bookCatogaryObject.Data.Rows.Count];
for (int i = 0; i < bookCatogaryObject.Data.Rows.Count; i )
{
DataClassArray[i] = new DataClass();
DataClassArray[i].collectionDataClass = new CollectionDataClass[bookCatogaryObject.Data.Rows[i].String.Count];
for (int m = 0; m < bookCatogaryObject.Data.Rows[i].String.Count; 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;
DataClassArray[i].collectionDataClass[m].collectionImage =
await GetImage(bookCatogaryObject.Data.Rows[i].String[m].CollectionThumbnail);
}
}
}
public static async Task<Texture2D> GetImage(string imageURL)
{
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(imageURL))
{
var asyncOperation = www.SendWebRequest();
while (asyncOperation.isDone == false)
{
await Task.Delay(1000 / 30);
}
if (www.isNetworkError || www.isHttpError)
{
Debug.Log($"{www.error}, URL:{www.url}");
return null;
}
else
{
return DownloadHandlerTexture.GetContent(www);
}
}
}