首页 > 解决方案 > 在调试期间,我注意到在加载资产或在 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;
}

标签: c#firebaseunity3dfirebase-realtime-databaseaugmented-reality

解决方案


你的协程不会等到 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)如果objnull由于上一行)

但是,为什么要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;

推荐阅读