c# - 在调试期间,我注意到在加载资产或在 for 循环中实例化 gameObject 时我的代码中断。代码没有错误
问题描述
我想用 UI 元素实例化 GameObject 并希望在其中填充数据。
我尝试在单独的函数或协程中运行 for 循环中的代码。我还尝试在 Firebase 逻辑中复制 for 循环。即使那样它也不起作用。唯一有效的是当我将代码放在 Firebase 逻辑之上时。
IEnumerator DoShowSomeProducts(Category category)
{
searchText.text = category.name;
foreach (Transform each in GetComponentInChildren<LayoutGroup>().transform)
{
GameObject.Destroy(each.gameObject);
}
// parse product
List<Item> productsInCategory = new List<Item>();
//Tried the for loop logic here works well but didn't need it here.
FirebaseDatabase.DefaultInstance.GetReference("Product").GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
Debug.Log("There is a fault");
}
else if (task.IsCompleted)
{
DataSnapshot snap = task.Result;
if (snap.ChildrenCount > 0)
{
foreach (var child in snap.Children)
{
print("Creating Item");
Item _item = new Item();
_item.url = child.Child("url").Value.ToString();
_item.image = child.Child("img").Value.ToString();
_item.code = child.Child("code").Value.ToString();
_item.price = child.Child("price").Value.ToString();
_item.category = child.Child("category").Value.ToString();
_item.descr = child.Child("descr").Value.ToString();
_item.link = child.Child("link").Value.ToString();
_item.name = child.Child("name").Value.ToString();
print("================================= \n Product\n" + _item.url + "\n" + _item.image + "\n" + _item.code + "\n" + _item.price
+ "\n" + _item.category + "\n" + _item.descr + "\n" + _item.link + "\n" + _item.name + "\n===========================");
productsInCategory.Add(_item);
//Here tried to run the for loop logic using separate functions and co-routines.
print("Added Product");
Debug.Log(_item.category);
}
}
}
});
for (int i = 0; i < productsInCategory.Count; i++)
{
print("PinCat Count = " + productsInCategory.Count);
Item item = productsInCategory[i];
GameObject obj = Resources.Load<GameObject>("Prefabs/ProductButtonPrefab");//this line breaks the code
GameObject clone = GameObject.Instantiate(obj);//this line brreaks the code.
clone.transform.parent = GetComponentInChildren<LayoutGroup>().transform;
clone.transform.localScale = Vector3.one;
clone.GetComponent<ProductButton>().nameText.text = item.name;
clone.GetComponent<ProductButton>().product = item;
clone.GetComponent<ProductButton>().categoryText.text = item.category;
clone.GetComponent<ProductButton>().priceText.text = item.price;
clone.GetComponent<ProductButton>().nameText.text = item.name;
print("Know Downloading Image");
WWW www = new WWW(item.image);
yield return www;
clone.GetComponent<ProductButton>().mainImage.sprite = Sprite.Create(www.texture, new Rect(0, 0, www.texture.width, www.texture.height), new Vector2(0, 0));
}
yield break;
}
解决方案
你的协程不会等到 firebase 有结果,所以for
循环总是在 firebase 的任何结果到达之前执行
=> 不会生成任何项目,因为productsInCategory
它始终是一个空列表。
(也比较这篇文章)
你应该把这两件事分成不同的方法。就像是
public void DoShowSomeProducts(Category category)
{
searchText.text = category.name;
foreach (Transform each in GetComponentInChildren<LayoutGroup>().transform)
{
GameObject.Destroy(each.gameObject);
}
// parse product
List<Item> productsInCategory = new List<Item>();
//Tried the for loop logic here works well but didn't need it here.
FirebaseDatabase.DefaultInstance.GetReference("Product").GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
Debug.Log("There is a fault");
}
else if (task.IsCompleted)
{
DataSnapshot snap = task.Result;
if (snap.ChildrenCount > 0)
{
foreach (var child in snap.Children)
{
print("Creating Item");
Item _item = new Item();
_item.url = child.Child("url").Value.ToString();
_item.image = child.Child("img").Value.ToString();
_item.code = child.Child("code").Value.ToString();
_item.price = child.Child("price").Value.ToString();
_item.category = child.Child("category").Value.ToString();
_item.descr = child.Child("descr").Value.ToString();
_item.link = child.Child("link").Value.ToString();
_item.name = child.Child("name").Value.ToString();
print("================================= \n Product\n" + _item.url + "\n" + _item.image + "\n" + _item.code + "\n" + _item.price
+ "\n" + _item.category + "\n" + _item.descr + "\n" + _item.link + "\n" + _item.name + "\n===========================");
productsInCategory.Add(_item);
//Here tried to run the for loop logic using separate functions and co-routines.
print("Added Product");
Debug.Log(_item.category);
}
// pass the list to the download routine
StartCoroutine(DownloadImages(productsInCategory));
}
}
});
}
private IEnumerator DownloadImages(List<Item> productsInCategory)
{
for (int i = 0; i < productsInCategory.Count; i++)
{
print("PinCat Count = " + productsInCategory.Count);
Item item = productsInCategory[i];
GameObject obj = Resources.Load<GameObject>("Prefabs/ProductButtonPrefab");
GameObject clone = GameObject.Instantiate(obj);
clone.transform.parent = GetComponentInChildren<LayoutGroup>().transform;
clone.transform.localScale = Vector3.one;
clone.GetComponent<ProductButton>().nameText.text = item.name;
clone.GetComponent<ProductButton>().product = item;
clone.GetComponent<ProductButton>().categoryText.text = item.category;
clone.GetComponent<ProductButton>().priceText.text = item.price;
clone.GetComponent<ProductButton>().nameText.text = item.name;
print("Know Downloading Image");
WWW www = new WWW(item.image);
yield return www;
// you should always debug things
if (!string.IsNullOrEmpty(www.error))
{
Debug.LogErrorFormat(this, "Download failed for item {0} at index {1} due to: {2}", item.name, i, www.error);
continue;
}
clone.GetComponent<ProductButton>().mainImage.sprite = Sprite.Create(www.texture, new Rect(0, 0, www.texture.width, www.texture.height), new Vector2(0, 0));
}
}
// this line breaks the code
你还说
GameObject obj = Resources.Load<GameObject>("Prefabs/ProductButtonPrefab");
此行假定您的对象位于其中,"Assets/Resources/Prefabs/ProductButtonPrefab"
因此请确保它位于Resources 文件夹中
(下一行也失败是显而易见的,因为你不能Instantiate(obj)
如果obj
是null
由于上一行)
但是,为什么要Resources
每次都加载它呢?在 for 循环之前只加载一次(或者在游戏开始时更好)
GameObject itemPrefab = Resources.Load<GameObject>("Prefabs/ProductButtonPrefab");
for (int i = 0; i < productsInCategory.Count; i++)
{
print("PinCat Count = " + productsInCategory.Count);
Item item = productsInCategory[i];
GameObject clone = GameObject.Instantiate(itemPrefab);
// ...
}
或直接将其放入“正常”资产中并在类似的字段中引用它
public GameObject ItemPrefab;
推荐阅读
- c# - 如何解析复杂的 JSON 结果
- javascript - Here API - 实现附近地点功能
- c# - 查询 SQLite 数据库中的行数和列数
- python - 如何在 R Markdown 中将 R 多元素向量转换为 Python 列表?
- android - 如何复制此 UI 行为
- r - 如何创建变量记录组中的任何成员是否具有 R 中的特征?
- qt - 如何防止将 QChartView 缩放为负 x 或 y 轴值
- python - 在嵌入 discord.py 中发送图像
- json - 在flutter中解析具有空键的JSON数据
- r - ggplot2 创建多个绘图但没有 facet_wrap