Search Unity

After being instantiated once and then destroyed, prefab can't be instantiated again (SOLVED)

Discussion in 'Scripting' started by Raidenwins, Feb 23, 2018.

  1. Raidenwins

    Raidenwins

    Joined:
    Dec 18, 2012
    Posts:
    132
    I am trying to accomplish the following: instantiate a prefab, destroy it, and then instantiate it again, destroy it again, and so on, and so forth. Let's call the prefab MyPrefab. MyPrefab has a MonoBehaviour script attached to it called MyPrefabMonoBehaviour.

    In another MonoBehaviour script, called PrefabScript, I instantiate the prefab like so:

    Code (CSharp):
    1. public class PrefabScript : MonoBehaviour
    2. {
    3.      public GameObject MyPrefab;
    4.      public GameObject CreatePrefab(Vector3 position, Quaternion rotation)
    5.      {
    6.          GameObject prefabInstance = (GameObject) Instantiate(MyPrefab, position, rotation);
    7.          return prefabInstance ;
    8.      }
    9. }
    And then, in the MonoBehaviour attached to MyPrefab, I destroy it:

    Code (CSharp):
    1. public class MyPrefabMonoBehaviour : MonoBehaviour
    2. {
    3.      private void DoSomething()
    4.      {
    5.          // Do something else
    6.          Destroy(gameObject);
    7.      }
    8. }
    This works fine the first time I instantiate the prefab, but when I try to do it a second time the value of MyPrefab in PrefabScript.CreatePrefab is null.

    I have also tried destroying the prefab from a third MonoBehaviour, which is where I am calling PrefabScript.CreatePrefab from, but the result was the same.

    What is the problem here?
     
    maroo111 likes this.
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Do you ever re-assign the value of MyPrefab? Are you sure you're referencing an asset for 'MyPrefab' ? If you select it in the inspector, it's not highlighting a game object in the hierarchy?
    That's all I can think of - otherwise it should be working, I think. :)
     
  3. I'm not 100% sure, because I can't test it right now, but my first guess is that the gameObject in the DoSomething on the prefab isn't pointing to the instance game object.
    I would try to pass the instance in after creation or call the destroy outside where you store the result of the CreatePrefab.

    Actually I was wrong. I was able to test it and it works for me.
     
    Last edited by a moderator: Feb 23, 2018
  4. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Are you trying to destroy the instantiated object or the prefab object?
     
  5. Raidenwins

    Raidenwins

    Joined:
    Dec 18, 2012
    Posts:
    132
    No, I am not re-assigning the value of MyPrefab. How would I do that?

    I don't understand your second question. Can you elaborate on that?

    If I select MyPrefab in the inspector, it's highlighting the prefab MyPrefab in 'Prefabs' folder in the Project tab, not a game object in the hierarchy. Does it have to (highlight a game object in Hierarchy, that is)?
     
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    No, all sounds good.. I was asking those questions to make sure you didn't give different answers.

    So, now are you trying to call the method on the MyPrefab script directly, or on a spawned (instantiated) copy('s) script? -- the destroy, I mean?
     
  7. Raidenwins

    Raidenwins

    Joined:
    Dec 18, 2012
    Posts:
    132
    The method that destroys the Prefab game object is called directly from the Update method of the MyPrefabMonoBehaviour script in MyPrefab. Something like this:

    Code (CSharp):
    1. public class MyPrefabMonoBehaviour : MonoBehaviour
    2. {
    3.      private void DoSomething()
    4.      {
    5.          // Do something else
    6.          Destroy(gameObject);
    7.      }
    8.  
    9.      void Update()
    10.      {
    11.          DoSomething();
    12.      }
    13. }
     
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Strange. If you want and can recreate a super simple scene just a cube instead of any prefab you might have had with those scripts, I could look at it if you post a unity package in the thread. Not sure what is the matter atm.. :) Instead of randomly guessing what might be wrong.
     
  9. Raidenwins

    Raidenwins

    Joined:
    Dec 18, 2012
    Posts:
    132
    I'll tinker with it some more to see if maybe I can't figure it out. If not, I may try to recreate a sample. Thanks though.
     
  10. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Yep, no problem, good luck.
     
  11. alexeu

    alexeu

    Joined:
    Jan 24, 2016
    Posts:
    257
    You maybe should use a clone of the prefab

    Code (CSharp):
    1. prefabClone = Instantiate(originalPrefab, position, rotation);
    2. Destroy(prefabClone , 0.25f);  // destroyed after 0.25 sec
     
  12. Raidenwins

    Raidenwins

    Joined:
    Dec 18, 2012
    Posts:
    132
    I am destroying a clone of the prefab MyPrefab. In fact, if I print out the name of gameObject before I destroy it:

    Code (CSharp):
    1. Print("Destroying " + gameObject.name);
    2.  
    3. Destroy(gameObject);
    the result is the following:

     
  13. Raidenwins

    Raidenwins

    Joined:
    Dec 18, 2012
    Posts:
    132
    After much debugging, Googling, and tinkering, I finally resolved the issue. The problem was the following: in the script where I wanted to create instances of MyPrefab, I needed a reference to PrefabScript. To accomplish that, I injected PrefabScript as a dependency (into the script in question) using Zenject. That is what caused the problem, because the injected instance of PrefabScript had a value of null for its MyPrefab field. I noticed that when I ran the game in a non-maximized window and started spotting a new instance of PrefabScript popping up in the Project tab, and when I clicked on it to view its details in the Inspector, low and behold, the MyPrefab field was null.

    So to fix the issue, instead of injecting PrefabScript I simply obtained it from the game object it was attached to, like this:

    Code (CSharp):
    1. PrefabScript myScript = GameObject.Find("SomeObject").GetComponent<PrefabScript>();
    And then myScript has a valid value for PrefabScript and everything works fine.

    Note that this is most likely not the optimal way to solve the problem. I believe Zenject has a way of correctly injecting types with prefab fields, but at this point I just want to get this to work and move on to something else.

    Thanks to everyone who tried to help though.
     
    Last edited: Feb 26, 2018
    unity_VLbZrsuvCDWe6A likes this.
  14. Kingjaw

    Kingjaw

    Joined:
    Jan 15, 2021
    Posts:
    1
    Hey I am having this same problem but where am I supposed to put the script for this? And also was it giving you an error message that says "The type of GameObject has been destroyed but you are still trying to access it"?
     
  15. Raidenwins

    Raidenwins

    Joined:
    Dec 18, 2012
    Posts:
    132
    Hi, which script are you referring to, the one that instantiates prefabs or the one that calls it (the script that instantiates prefabs, that is)? And it's been a while since I worked on this issue so I am not 100% sure, but that error message does sound familiar.