Instantiated UI objects not appearing immediately

Hi, I am seeing a problem when instantiating rows in the UI whereby I have to click twice on the shopkeeper for the items to appear. On the first click, the child objects are destroyed and the list appears empty. The ‘content’ gameobject in the hierarchy is also empty. Then (regardless of whether I leave the UI open or close it) after the second click on either of my two shopkeepers, the behaviour is as expected.

        private void RefreshUI()
        {
            foreach (Transform child in listRoot)
            {
                Destroy(child.gameObject);
            }

            Debug.Log(currentShop.GetShopName());
            foreach (ShopItem shopItem in currentShop.GetFilteredItems())
            {
                RowUI newRow = Instantiate<RowUI>(rowPrefab, listRoot);
                Debug.Log(newRow.name);
            }
        }

Note the Debug.Log line I added to check if the instantiation was creating a genuine object. This correctly logged out “Row (clone)” for all 3 new rows on both the first and second click.

I’m curious that you’re getting any items even on the second click…

foreach (ShopItem shopItem in currentShop.GetFilteredItems())
{
    RowUI newRow = Instantiate<RowUI>(rowPrefab, listRoot); //newRow knows nothng about shopitem.
     Debug.Log(newRow.name); //just says the row's name, still nothing about the shopItem
} //Shouldn't we set up the row with the  shop item?

Hi Brian, Thanks for the response. Yes I haven’t got far enough into the course yet to start populating rows with ShopItem data (I think that might be the next lecture). This was just to test that the ‘Row’ gameobjects were being created in the hierarchy. It should be one ‘default’ row as laid out in the prefab for each ShopItem received from GetFilteredItems().
The results show that I am getting the correct number of items from GetFilteredItems() so that side of it is fine. The original rows are being destroyed correctly so that side is also fine. In fact, the second click shows that even the logic for instantiating from a prefab under that specific parent is also fine. It has me rather baffled.

Further to this, after some more testing in game, the shop UI is initially disabled but with the content provided in the prefab. If, without any interaction with the Shopkeepers, I manually enable the shop UI, it appears and empties itself of all rows immediately. After that, the behaviour with the shopkeepers is as expected - a single click is enough to populate the shop with the number of default rows determined by the number of responses from GetFilteredItems(). Curiouser and curiouser…

Apologies this turned out being a longer message than I’d hoped.

Apologies, I thought you were further along.

Post the whole ShopUI file, and I’ll see if I can trace the logic.

Well it appears that rebooting my machine has ‘fixed’ the issue. Simply restarting Unity didn’t last night. Panic over (for now), I can move onto the next lecture :slight_smile: … Thanks for your time - code is posted below anyway for reference.

using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using RPG.Shops;
using UnityEngine;

namespace RPG.UI
{
    public class ShopUI : MonoBehaviour
    {
        [SerializeField] TextMeshProUGUI shopName;
        [SerializeField] Transform listRoot;
        [SerializeField] RowUI rowPrefab;

        private Shopper shopper = null;
        private Shop currentShop = null;

        // Start is called before the first frame update
        void Start()
        {
            shopper = GameObject.FindGameObjectWithTag("Player").GetComponent<Shopper>();
            if(shopper == null) return;
            shopper.activeShopChange += ShopChanged;

            ShopChanged();
        }

        private void ShopChanged()
        {
            currentShop = shopper.GetActiveShop();
            gameObject.SetActive(currentShop != null);
            if(currentShop == null) return;

            shopName.text = currentShop.GetShopName();
            RefreshUI();
        }

        private void RefreshUI()
        {
            foreach (Transform child in listRoot)
            {
                Destroy(child.gameObject);
                Debug.Log("Destroying " + child.gameObject.name);
            }

            Debug.Log(currentShop.GetShopName());
            foreach (ShopItem shopItem in currentShop.GetFilteredItems())
            {
                RowUI newRow = Instantiate<RowUI>(rowPrefab, listRoot);
                Debug.Log("Creating Row " + newRow.name);
            }
        }

        public void Close(){
            shopper.SetActiveShop(null);
        }
    }
}

I wish I could say that never happens, but… it happens. Glad it’s sorted now. I don’t see anything suspicious in the code.

For anyone else seeing this issue, I just reached lecture 23 (22_SH_SAB) and Sam addresses this issue directly.
It is due to the fact that we left the ‘Quest List UI’ component attached when we made the ScrollView prefab. This causes a race condition and can do funky things with redrawing contents.