Search Unity

Resources.Load in list changes list content (C#)

Discussion in 'Scripting' started by Dariuszz, Feb 10, 2016.

  1. Dariuszz

    Dariuszz

    Joined:
    Sep 1, 2014
    Posts:
    3
    Hi,

    I have a problem with Resources.Load. I am trying to create a GameObject and initialize with Resources.Load. Then I create a list, modify the transform.position of the GameObject and start adding the GameObject to the list. The modifying and adding is done three times. The problem is: after all this is done, the list will only contain the last GameObject, but three times. Example:

    Code (CSharp):
    1. GameObject a = (GameObject)Resources.Load("object");
    2. System.Collections.Generic.List<GameObject> list = new System.Collections.Generic.List<GameObject>();
    3. a.transform.position = new Vector2(1, 1);
    4. list.Add(a);
    5. a.transform.position = new Vector2(2, 2);
    6. list.Add(a);
    7. a.transform.position = new Vector2(3, 3);
    8. list.Add(a);
    If I were to debug log the list afterwards, it would output (3.0, 3.0, 0.0) three times.
    My question is: Why is this happening and how could I add this GameObject to the list otherwise?
     
  2. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,624
    You are adding the same GameObject to the list 3 times. What are you trying to achieve here? Create 3 separate GameObject instances in the scene? You haven't instantiated anything in the scene.

    Resources.Load will load the object from disk into memory, but it's not going to create an instance in your scene hierarchy that you can modify the transform on. You don't have any calls to Object.Instantiate, which is required to create a scene instance from a GameObject on disk.

    You will need to instantiate your object in the scene 3 times, modify the transforms on these 3 instances, and add each separate instance to your list.
     
    Dariuszz likes this.
  3. Dariuszz

    Dariuszz

    Joined:
    Sep 1, 2014
    Posts:
    3
    Hey thanks for the reply.
    I never specified I wanted to create an instance (I do want to instantiate later on, but not in the example), all I want is to use Resources.Load to initialize a GameObject. I also want this same GameObject several times in a list, but with different information (the new positions in my example above). With a new GameObject this is possible, but with Resources.Load it seems to produce the problem I mentioned above.

    I also just realized that with a new GameObject this is possible, because after calling "new GameObject", an instance is created. I will just have to pass on the information (the positions) in the list and instantiate the Resources.Load GameObject with the list of positions.
     
  4. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,624
    You said " I am trying to create a GameObject," and by that I assumed you meant you wanted to create it in the scene and not just modify the original's contents. By loading the GameObject with Resources.Load, you're not creating anything -- you're simply loading a reference to the GameObject on disk. And by adding it to the list 3 times, you're creating 3 references to the exact same on-disk game object 3 times. You're changing the transform.position on the same GameObject 3 times also so you're overwriting your old change each time. The normal way of working with Resources.Load for GameObjects is to load it, then instantiate it from the prefab reference (what you loaded from Resources.Load).

    The problem is, Resources.Load is loading one single instance -- the one on disk. You can't give a single GameObject 3 different positions -- the class object can only store one set of data, which means one transform and one position. This is how class instances work in all programming languages. The only way you can store 3 different positions, one in each object, by instantiating the object 3 times first, then changing the position on those 3 instances. Or, like you realized, you could store your initialization data separately from your objects such as saving 3 Vector3's in a list and use that data to instantiate the GameObjects later. (The Vector3's are structs and therefore are stored by value and not by reference so storing the same struct in the list 3 times will actually store 3 separate values.)

    Calling new GameObject is the same as using Object.Instantiate without the position and rotation parameters. It will create an instance of the GameObject and it will appear in the scene hierarchy.
     
  5. Dariuszz

    Dariuszz

    Joined:
    Sep 1, 2014
    Posts:
    3
    Ye I just read about the differences between value types and reference types and this makes sense now. I have been treating the variables as value types all the time. Good to know this from now on. I decided I will just instantiate first and modify information afterwards.

    Thanks for the help and the info.