Search Unity

Do lists store child objects?

Discussion in 'Scripting' started by Denisowator, Mar 5, 2019.

  1. Denisowator

    Denisowator

    Joined:
    Apr 22, 2014
    Posts:
    918
    I'm using a GameObject list (List<GameObject>) to store objects, then reinsert them later.

    If I put a GameObject into a list while it has children, will those children also be stored, or will only the base parent GameObject be stored?

    And if they don't store GameObjects along with their children, what can I do/use to keep a reference/copy of a GameObject and its children?
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    A list will contain only what you put in the list.

    So no it won't store references to those child gameobjects. It'll only contain the gameobjects you put in it.

    You can of course get at those child gameobjects by looping over the children of the members of the list.

    What is it you're trying to accomplish?

    As in, what is your end goal here?
     
  3. Denisowator

    Denisowator

    Joined:
    Apr 22, 2014
    Posts:
    918
    I have a UI element with a lot of children, and some of those have their own children. The UI element's children (and therefore also the grandchildren) are changed at runtime. So I want to keep multiple references/copies of the various groups of children and grandchildren, so that I can then switch between them.

    Example:
    Game start
    Blue square, red square, yellow square (with green square child).
    store squares
    remove squares from scene and replace with new ones
    store new squares
    when desired, remove new squares and get original squares back
    when desired, re-remove original squares and get back new squares

    The switching of children and grandchildren is done by clicking on objects in the scene. So if I click on object 1, I want the UI element to show a certain group of squares, I then want to store those squares. If I click on object 2, I want to be able to replace the squares with some new ones, then store those somewhere else. I then want to be able to just click back and forth between the objects and have them show their respective squares.
     
    Last edited: Mar 5, 2019
  4. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Technically, when you put a GameObject into a list, what you are saving is a reference to that GameObject. It's like you have its phone number. The GameObject still exists in your scene and hasn't moved; you just have a way to talk to it.

    If some outside force alters the GameObject, you've got a reference to the modified version, not a copy of the original. If the GameObject gets deleted, the fact that you put it into your list won't allow you to resurrect it.

    If you want to duplicate the entire object so that there's now 2 of them in your scene, you can use Instantiate(). Instantiate() will copy all of the children, too.
     
  5. Denisowator

    Denisowator

    Joined:
    Apr 22, 2014
    Posts:
    918
    Well I am instantiating them, but I am doing so through the list. And now that I actually tried changing the names of the scene objects as I'm storing them in lists, yeah they are just references.

    How could I efficiently store copies of the objects? Keep in mind the number of different lists of objects is not static, and could be very large (like 10+ lists, each containing 16 objects). I don't think it would be wise to just shove some copies into the scene and keep them out of view until needed.
     
  6. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Keeping a couple hundred objects in your scene out-of-view until needed is not necessarily a bad plan. (Remember you can use SetActive(false) to ensure they won't render or interact with physics, etc.) That's not a huge number.

    If you don't want to have the objects in your scene, but you want to be able to re-create them on demand, then you need to serialize all of the object data (or at least the subset of data that you care about). Conceptually, you are separately storing every detail of the object--its size, position, rotation, name, color, etc.--so that you can build up a copy "from scratch" later on. This is basically how all save/load features work.

    Since Unity already has to do this in order to save your scene files, there should already be some features related to serializing and deserializing game objects built into Unity. If you're going to go that route, you should look for those rather than building your own thing from scratch.

    But very often you don't actually need to know every detail of every separate object, because they follow some kind of pattern with only a few unique details. For instance, if you have a menu with a bunch of buttons on it, then probably all you really need to save are the button labels (text/icons) and what they do; the general appearance of the buttons is going to be the same for all of them (probably based on a prefab) and their layout is going to be set automatically, so you don't need to save that stuff.
     
  7. Denisowator

    Denisowator

    Joined:
    Apr 22, 2014
    Posts:
    918
    Okay, so I've been looking at serialization for the past day, and I honestly can't figure it out so far. I know how to serialize data, it's just I don't know how to serialize information about 16 objects and their children, then deserialize while keeping the children parented to the parents and stuff (and in the correct order). At least not in an efficient way.

    I was thinking. The objects that should store those squares, aren't actually going to stay forever in the scene, they'll come and go whenever. So what if I just instantiate a copy of the UI element, in each script instance that does the list storing. Therefore each object will have its squares, and I'll just switch between the UI element copies.

    I would just need to figure out a way of keeping only one visible. Like maybe when I'm about to open one, run a foreach loop looking for all the instances, whatever it finds open, close it, then at the end of the loop open the correct one.
     
    Last edited: Mar 6, 2019
  8. Denisowator

    Denisowator

    Joined:
    Apr 22, 2014
    Posts:
    918
    Okay got it working finally.

    In "OnMouseDown" if I'm within range of a dead enemy, it does its thing for creating the squares, then it runs through all the objects in scene tagged something (e.g. "click target"). It checks a certain bool, if that bool is true, it calls that current loop object's code to close its UI element copy. And after the loop is done, it opens the current object's UI element.

    Also when removing the object, I'm calling "Destroy()" on the instantiated UI element, and then the object itself.