Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Instantiating prefabs

Discussion in 'Scripting' started by dseengal, Jun 18, 2021.

  1. dseengal

    dseengal

    Joined:
    Jul 16, 2020
    Posts:
    15
    Hi..

    I need help with instantiating a new prefab in place on another...

    I have an AR app that places prefab1 at the start of the application.. I want to replace prefab1 with prefab 2 when a UI button is clicked.. Right now with the scripting I m trying (as given below).. the prefab2 is not visible.. but i believe it is being instantiated because the audio attached with prefab2 starts playing but the 3D elements are not visible..

    I don't know how to fix it.. I would highly appreciate if someone can guide me in resolving this..

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.XR.ARFoundation;
    6. using UnityEngine.XR.ARSubsystems;
    7.  
    8. public class FloorMap : MonoBehaviour
    9. {
    10.     public GameObject prefab1;
    11.     public GameObject prefab2;
    12.    
    13.     public Button butt;
    14.    
    15.     public void map()
    16.     {
    17.         prefab1.SetActive(false);
    18.        
    19.         Instantiate(prefab2, transform.position, Quaternion.identity);
    20.  
    21.         butt.gameObject.SetActive(false);
    22.  
    23.     }
    24.  
    25. }
     
  2. Nefisto

    Nefisto

    Joined:
    Sep 17, 2014
    Posts:
    324
    First of all, when you call
    prefab1.SetActive(false);
    you're trying to change the state of the prefab asset, not the runtime obj that exist in the scene unless you've dragged the object from the scene but then this isn't exactly a prefab and if you remove it from the scene in runtime you'll have problems.

    I suspect that your prefab2 is equal or a variant of prefab one, so as I said before when you set the active state of prefab to false all following prefabs that you instantiate from this one will be created inactive because the prefab is inactive.

    Take a look at the hierarchy to make sure if this is or isn't being instantiated

    One good approach imo is to make an empty obj that has both objs and then you simply activate and deactivate the one that you need to show at some moment.
     
  3. dseengal

    dseengal

    Joined:
    Jul 16, 2020
    Posts:
    15
    Hi.. thank you for you help... would it be possible for you to explain more about creating one object and assigning both prefabs to it ... I m new to c# and not able to figure this out.. sorry for the trouble..
     
  4. Omniglitch

    Omniglitch

    Joined:
    May 29, 2017
    Posts:
    37
    On line 19, when you call Instantiate, for the second parameter you provide transform.position. Note that this is the position of the game object that has the FloorMap script attached. Perhaps this is not the position you want and that's why you're not seeing the game object appear.

    Also as a side note, it's not great for performance to call Instantiate and Destroy a lot in your main game loop because it can create a lot of garbage, and the garbage collector can cause stutters. If you'll be switching back and forth between displaying two objects, have them both already instantiated, and use SetActive to determine which is visible. If you're creating lots of objects, e.g. firing bullets, look into using object pools.
     
  5. Nefisto

    Nefisto

    Joined:
    Sep 17, 2014
    Posts:
    324
    IDK if I understood what you mean by "assigning both prefabs to it" but I'll try to explain the problem in your initial script. When you create your public variable of type GameObject, it basically accepts that you threw any kind of object there because GameObject is the base type for unity purposes, this can or cannot be a prefab. Let's say that you have inserted an object called A that exists in your scene to this variable and then tries to use it as a prefab, things will work just fine because a prefab is only a template to be followed when you try to create an object, so if you change object A position, components, properties or anything else the new instantiate clones of A will follow the changes, the problem with using runtime objects is that this is only an instance of some object that exists in memory and can be removed at any point for any reason, by Destroy(), change the scene, so on. So is better to drag the template, aka prefab, from project to this public variable, because then it's an asset that exists in your HD, so this doesn't represent an instance of the template, and as an asset, this will not be removed (you can remove... but I doubt that you'll want this). When we make changes in some game object property in code, normally we want to change instance properties and not the prefab property, but in your code, you're making a change to the prefab not to instance.

    Now about your code

    Code (CSharp):
    1.     public void map()
    2.     {
    3.         // this will change the template state, so every instance of this template will have this state changed also
    4.         // this will make every object that is created from this template start inactive in the hierarchy
    5.         prefab1.SetActive(false);
    6.         // What you probably want is to find the prefab1 instance and then make it inactive
    7.      
    8.         var instanceOfPrefab2 = Instantiate(prefab2, transform.position, Quaternion.identity);
    9.        
    10.         // prefab2 is the template
    11.         // instanceOfPrefab2 is the instance
    12.        
    13.         butt.gameObject.SetActive(false);
    14.     }
    About you being able to hear the object sounds but can't see it
    He is right, so this is probably the cause


    Let me suggest a simple code to you

    Code (CSharp):
    1. public class FloorMap : MonoBehaviour
    2. {
    3.     public Button invertButton;
    4.     public GameObject itemA, itemB; // this isn't a prefab, its a reference to runtime gameobjects
    5.  
    6.     private void Awake()
    7.     {
    8.         invertButton.onClick.AddListener(Invert); // You can do this in inspector too, it's a matter of choise
    9.     }
    10.  
    11.     public void Invert()
    12.     {
    13.         if (itemA.activeInHierarchy)
    14.             ActivateItemB();
    15.         else
    16.             ActivateItemA();      
    17.     }
    18.  
    19.     private void ActivateItemA()
    20.     {
    21.         itemA.SetActive(true);
    22.         itemB.SetActive(false);
    23.     }
    24.  
    25.     private void ActivateItemB()
    26.     {
    27.         itemA.SetActive(false);
    28.         itemB.SetActive(true);
    29.     }
    30. }
    Hope this helps, N
     
  6. dseengal

    dseengal

    Joined:
    Jul 16, 2020
    Posts:
    15
    Wonderful.. this worked... thank you so much for your help.. :)