A list of objects from a c# script into a UI panel dynamically at run time

Not a specific coding issue, there’s no roadblock per se - but i’m having a scripting issue and hoping to find some help.

The short of it is: i have objects that get added to a list at runtime. I have a prefab to display the values in these objects at runtime in an UI panel. All these things are in place. I can do it by hand, no problem.

What i’m having trouble with is finding a tutorial to do it dynamically at run time. I have to be able to add, remove and alter said objectives without having to do a bunch of UI work. There’s some available with very varying styles of approaching this, but i’m not having success with any of them. Building UI elements dynamically from script seems like a very basic task, so it’s certainly possible i’ve overlooked some issue. Thank you in advance to any and all that might be able to help.

1 Like

So you need a few pieces of this:

  1. You need some way to call a function when the list is changed. How best to do this depends greatly on what the code looks like for changing the list, but shouldn’t be too difficult to find.
  2. When that happens, you need to create a new UI object from a prefab, or destroy the appropriate existing UI object.
  3. You need to handle the layout. the various LayoutGroup components in the UI system make this really easy.

It sounds like step 1 may be where you’re having the most challenges? If so, post the code where the list changes and we can start working from there.

2 Likes

Everything that @StarManta said above is spot-on, and let me add one more thing:

A really useful way to work with dynamic Unity UI lists is to put a single instance of your “list item” under some kind of layout object, as Star said above, and then when you build your list you simply clone that object as many times as you need, while keeping its parentage.

This would be what your saved scene hierarchy would look like:

5289114--530703--Screen Shot 2019-12-16 at 2.38.43 PM.png

And after the code runs, you might have:

5289114--530709--Screen Shot 2019-12-16 at 2.39.02 PM.png

To do this, you would use a construct like the following:

var item = Instantiate<GameObject>(
    MyExampleObjectReferenceFromWithinTheScene, transform);

That final argument ensures it is stuck as a peer to the original one.

Usually I turn the example one off with .SetActive(false) inside of Start(), and then after Instantiating each item, I .SetActive(true) it, then customize it based on whatever sub-object bits it needs. Having a handy script at the root of the item can be very helpful here.

1 Like

Thank you both, StarManta and Kurt-Dekker, your help is appreciated. I’m slowly but surely getting there.

The issue is not really with the list changing, i think i can manage that as soon as i get the list created. I made a working mock-up to try and figure this out, and i’m now able to instantiate and gotten pretty far, but i still cant get the clones to show up at run time.

I’ve used the clone method proposed by Mr. Dekker, to keep it as simple as possible.

I have a panel, where i have an image, that has a few child objects. This is as suggested. I have a variable in my script that is connected to this this image via d’n’d in the ui, and the constructor method fills the child elements (name, description), also connected with d’n’d in the ui.

My Template object is as follows:

public class EqSlider : MonoBehaviour
{
    public RawImage epict;
    public Text ename;
    public Text edesc;

    public EqSlider(RawImage a, string name, string desc)
        {
        ename.text = name;
        edesc.text = desc;
        epict.texture = a.texture;
        }
}

I have the elements connected via the UI:

In my main script:

public EqSlider eqOrg;

And then:

    public void GenerateEqList()
    {
        foreach (Equipment eip in gearList)
        {

            EqSlider _go = Instantiate(eqOrg,transform);
            _go.edesc.text = "desc";
            _go.ename.text = "name";
            _go.epict.texture = null;
        }
    }

There’s Equipment type objects in a list, that’s populated at main script Start(). After it’s populated, the method GenerateEqList() is called.

It all runs, but it’s not showing up as in Mr. Dekker’s second image, nor is it visible. As of right now, based on what i have on the list (one object), it should create a single instantiated EqSlider with the manually added values “desc” and “name”.

The template EqSlider is inside a vertical layout group as suggested.

I’m comfortable with filling the instances with useful data as soon as i get this dummy version working as intended. I bet my bottom dollar that i’m just not understanding something very basic.

There are some working versions online, which i could copy and mess with to make them work - but i’d rather understand what i’m doing than copypaste, so that said, both your help is again, appreciated.

@MikaV84

You should check the UI basics tutorials, take your time and go through all of those. UGUI can be really convoluted to work with… even the basics setups will mess up layout easily (content size fitter, layout element, vertical layout group etc).

For example, this can be done easily, once you’ve done the basics tutorials, note: to parent children (to panel, scrollRect etc), use SetParent with worldPositionStays: false option:

5290827--530964--listView.gif

Here I’m adding items runtime when pressing a key (instantiate a row prefab). Deletion works as well in similar manner. Row element is a RectTransform with child image and text RectTransforms.

BTW - isn’t this a UI question?

1 Like

If you instantiated them, they’re very likely present in the scene. Did you press PAUSE in the editor and go look for them in the scene after they were created? Where were they? Were they parented where you told them to be? Were they parented somewhere else? If so, fix that. If they weren’t present, then likely your instantiate code did not run. Why not? Put Debug.Log() statements in and try to figure out what’s happening.

This is all very basic code-to-scene-to-code troubleshooting… it’s the easiest workflow in the world once you start using it, and it can almost instantly surface whatever problem you’re having.

Good starting point for this is unity UI dropdown component. It does just that - dynamicaly fills dropdown list with preconfigured items. Works both in editor and runtime

https://bitbucket.org/Unity-Technologies/ui/src/2019.1/UnityEngine.UI/UI/Core/Dropdown.cs