Search Unity

Resolved Instantiate and destroy the original gameobject

Discussion in 'Scripting' started by shanataru, Jan 5, 2021.

  1. shanataru

    shanataru

    Joined:
    Mar 4, 2019
    Posts:
    13
    Hello,
    I do not understand why the code below does not work for me.

    I am trying to instantiate a game object from a game object which I have saved as a class member. The cloned game object should have the same properties as the original with a slightly different mesh (the baked mesh from a particle system). This cloned version should become the original game object in the next update.

    When I run this in play mode I get this error:
    MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.


    Code (CSharp):
    1.         for (int i = 0; i < bPart.Count; ++i)
    2.         {
    3.             bPGO p = bP[i]; //my class
    4.             //... make some changes on p.m_GO
    5.  
    6.             GameObject newGO = Object.Instantiate(p.m_GO, p.m_GO.transform.position, p.m_GO.transform.rotation, p.m_GO.transform.parent);
    7.             Object.Destroy(p.m_GO);
    8.             p.m_GO = newGO;
    9.         }

    Originally, I kept the original game object and just changed its mesh properties, but due to various reasons, I might have to create a completely new game object every update.

    I really appreciate any help you can provide.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,740
    The answer is always the same... ALWAYS. It is the single most common error ever. Don't waste your life on this problem. Instead, learn how to fix it fast... it's EASY!!

    In this case, you're destroying something and then trying to use it again.

    Some notes on how to fix a NullReferenceException error in Unity3D
    - also known as: Unassigned Reference Exception
    - also known as: Missing Reference Exception

    http://plbm.com/?p=221

    The basic steps outlined above are:
    - Identify what is null
    - Identify why it is null
    - Fix that.

    Expect to see this error a LOT. It's easily the most common thing to do when working. Learn how to fix it rapidly. It's easy. See the above link for more tips.

    This is the kind of mindset and thinking process you need to bring to this problem:

    https://forum.unity.com/threads/why-do-my-music-ignore-the-sliders.993849/#post-6453695

    Step by step, break it down, find the problem.

    To me, it is always simpler to keep an original game object, make clones of it and destroy the clones, then make fresh clones. This eliminates the confusion of line 8 above, where "the old one is now the new one," which can be baffling to what is going on.
     
  3. shanataru

    shanataru

    Joined:
    Mar 4, 2019
    Posts:
    13
    Thank you for your feedback.

    I understand that I have the null reference error because somehow I am destroying the game object saved in the class member p.m_GO.

    When I make the assignment at line 8, I thought that I would get the newly instantiated object saved, and the next call will access this saved clone, but I guess it did not work because it was just a local variable. I assume that calling destroy many times on the same game object does not produce any error.

    Regarding cloning things, your idea of keeping the original alive, while modifying the instances, is neat and I will try to use that instead.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,740
    Usually the first thing I do is turn off the thing:

    Code (csharp):
    1. public GameObject ExampleThingy; // drag the thing in here from the scene
    2.  
    3. void Start()
    4. {
    5.  ExampleThingy.SetActive(false);
    6. }
    7.  
    Then when I want one:

    Code (csharp):
    1. var copy = Instatiate<GameObject>( ExampleThingy);
    2. copy.SetActive(true);
    and off you go
     
    HanwenWu98 likes this.
  5. shanataru

    shanataru

    Joined:
    Mar 4, 2019
    Posts:
    13

    This works well, thank you for your patience.

    In the end I am storing the instantiated copies in a list and before baking a new mesh into the original I destroy them and clear the list.

    I still have not found out how to actually store one instantiated object into the GameObject variable as a class member (from original post the line 8 is useless and the next call on p.m_GO returns null), but that is probably my inexperience in C# references, which I suspect will not be the same as for C++ :oops:
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,740
    What is a
    bPGO
    in your first script? If that's a class that's fine. If that's a struct, what you're doing will absolutely NOT work, because structs are value types and line 3 in that script makes a complete copy to the variable
    p
    , leaving the original in the array unmodified by future operations.
     
  7. shanataru

    shanataru

    Joined:
    Mar 4, 2019
    Posts:
    13
    It is a struct, actually. I did not know that it makes a hard copy, I feel ashamed :confused:
    I automatically created a struct thinking it was similar to a class except some privacy stuff.
    I have much to learn for C#
     
    Kurt-Dekker likes this.
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,740
    You are on the right track but the wrong language! I had the same issue originally. You're thinking of C++:

    https://www.geeksforgeeks.org/structure-vs-class-in-cpp/

    In C# the main difference is that a struct is a value type and a class is a reference type.

    Glad you're back on track.