Search Unity

Respawn a Pickup Using Instantiate

Discussion in 'Scripting' started by ytwithlove, Jul 27, 2014.

  1. ytwithlove

    ytwithlove

    Joined:
    Mar 14, 2013
    Posts:
    26
    Hey guys! Have a question about instantiating a prefab.

    I followed the Instantiate steps in the Unity manual and was able to get a prefab to show up on the screen in a grid or a circle. I would like to have my prefab respawn in the same place after it is picked up by the player. How would I go about doing this?

    I've tried just about everything from using Yield WaitForSeconds to SetActive as false or true with no progress on getting the prefab to show up again.

    Any suggestions?
     
  2. SubZeroGaming

    SubZeroGaming

    Joined:
    Mar 4, 2013
    Posts:
    1,008
    You can create a spawn script.

    Have a bool that checks if you need to spawn or not. If you pick up the object, set the bool true, and spawn another one


    Or...


    Use a coroutine to give the elision that you picked it up, set the GameObject in active wait 3 seconds, then set it active.

    Paste your code for what you have tried
     
  3. domkia

    domkia

    Joined:
    Aug 19, 2012
    Posts:
    99
    ^ coroutine, since you can use yield waitforseconds
     
  4. der_r

    der_r

    Joined:
    Mar 30, 2014
    Posts:
    259
    SubZeroGaming likes this.
  5. ytwithlove

    ytwithlove

    Joined:
    Mar 14, 2013
    Posts:
    26
    Ok here is what I've tried...
    I have a capsule tagged as Player. I have the prefabs tagged as Pickup.

    In the Player script, I have the OnTriggerEnter method where the prefab is picked up by the player. I have the coroutine following this where the prefab should reappear after 3 seconds.

    I can get the prefab to be picked up by the player but it doesn't reappear after 3 seconds. I've tried using the coroutine in both the player script and outside the player as a respawn script placed on an empty game object. Neither seem to be able to work.

    Thanks for the suggestion of using Invoke der_r but I have no idea how to set that up in my code even after reading the Unity doc. I may be over-thinking it a bit at this point.

    Here's my code - maybe there's something I'm missing.

    Code (CSharp):
    1. public class Player : MonoBehaviour
    2. {
    3.     public float movementSpeed = 5.0f;
    4.     CharacterController character;
    5.  
    6.  
    7.     public GameObject prefab;
    8.     public int numberOfObjects = 1;
    9.     public float radius = 5f;
    10.    
    11.     bool PickedUp = false;
    12.  
    13.     // Use this for initialization
    14.     void Start ()
    15.     {
    16.  
    17.     }
    18.  
    19.     // Update is called once per frame
    20.     void Update ()
    21.     {
    22.         //Get the Character Controller//
    23.         CharacterController character = GetComponent<CharacterController>();
    24.  
    25.         //Character Movement//
    26.         float FBSpeed = Input.GetAxis("Vertical") * movementSpeed; //forward and back movement
    27.         float LRSpeed = Input.GetAxis("Horizontal") * movementSpeed; //left and right movement
    28.  
    29.         Vector3 speed = new Vector3(LRSpeed, 0, FBSpeed); //get the Vector for the speed
    30.         speed = transform.rotation * speed;  //storing the speed
    31.         character.Move(speed * Time.deltaTime); //get the character movement speed
    32.  
    33.     }
    34.    
    35.     void OnTriggerEnter(Collider other)
    36.     {
    37.         if (other.gameObject.tag =="Pickup")
    38.         {
    39.             other.gameObject.SetActive(false);
    40.             StartCoroutine(RespawnItem());
    41.         }
    42.     }
    43.  
    44.     IEnumerator RespawnItem ()
    45.     {
    46.         if(PickedUp)
    47.         {
    48.             int respawnTime = 3;
    49.             yield return new WaitForSeconds(respawnTime);
    50.             for (int i = 0; i < numberOfObjects; i++)
    51.             {
    52.                 float angle = i * Mathf.PI * 2 / numberOfObjects;
    53.                 Vector3 pos = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius;
    54.                 Instantiate(prefab, pos, Quaternion.identity);
    55.             }
    56.             Debug.Log ("Spawned!");
    57.         }
    58.         PickedUp = false;
    59.     }
    60. }
    The Respawn script:
    Code (CSharp):
    1. public class Respawn : MonoBehaviour
    2. {
    3.     public GameObject prefab;
    4.     public int numberOfObjects = 1;
    5.     public float radius = 5f;
    6.     bool PickedUp = false;
    7.  
    8.     void OnTriggerEnter(Collider other)
    9.     {
    10.         if (other.gameObject.tag =="Pickup")
    11.         {
    12.             other.gameObject.SetActive(false);
    13.             StartCoroutine(RespawnItem());
    14.         }
    15.     }
    16.  
    17.     IEnumerator RespawnItem ()
    18.     {
    19.         if(PickedUp)
    20.         {
    21.             int respawnTime = 3;
    22.             yield return new WaitForSeconds(respawnTime);
    23.             for (int i = 0; i < numberOfObjects; i++)
    24.             {
    25.                 float angle = i * Mathf.PI * 2 / numberOfObjects;
    26.                 Vector3 pos = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius;
    27.                 Instantiate(prefab, pos, Quaternion.identity);
    28.             }
    29.             Debug.Log ("Spawned!");
    30.         }
    31.      
    32.         PickedUp = false;
    33.     }
    34. }
     
  6. der_r

    der_r

    Joined:
    Mar 30, 2014
    Posts:
    259
    I never see you setting PickedUp to true.
     
  7. ytwithlove

    ytwithlove

    Joined:
    Mar 14, 2013
    Posts:
    26
    This is interesting...

    Thanks for the catch der_r on not setting PickedUp to true. That helped actually get the cube to appear again, but now it's only showing 1 cube in 1 place. It looks like all the cubes are respawning in the same place instead of in another grid area.

    I tried placing the Respawn script in an empty game object, duplicating, then placing in different areas but this did not change the behavior of the scene.

    How would I make it so the cubes would show up in a separate grid area or randomly on the plane?
     
  8. ytwithlove

    ytwithlove

    Joined:
    Mar 14, 2013
    Posts:
    26
    Any suggestions guys? Really stumped on this one. I have no idea why all of the cubes are respawning in one place.
     
  9. der_r

    der_r

    Joined:
    Mar 30, 2014
    Posts:
    259
    In your for-loop where you are re-spawning the cubes, it says "for(int i =0; i < numberOfObjects; i++)". But "numberOfObjects" is set to 1, which means the loop only gets 1 iteration.
     
  10. ytwithlove

    ytwithlove

    Joined:
    Mar 14, 2013
    Posts:
    26
    That was one of the first things I tried. I changed numberOfObjects = 5 and it still produced the same result.
    But I did see that as a possible cause to the problem right away - just wish it was the answer. Had a feeling this was going to be a tricky one.
     
  11. ytwithlove

    ytwithlove

    Joined:
    Mar 14, 2013
    Posts:
    26
    Ok this is interesting. I went into my Player script and changed the number of objects to 5. I have it public anyway so it would be available to be changed in the inspector, but I wanted to satisfy my curiosity and changed the initial value.

    When I run the scene, I can see the first set of cubes in the grid formation. When I start to pick them up, I'm able to see some of the cubes being instantiated again. So at least I know the loop is working properly.

    But here's the interesting part, there are only 5 cubes showing up in the scene. Each of these 5 cubes has 10 cubes stacked in the same place. When you pause the game and select the cube, you can move each individual cube to a place on the stage. But the cubes never form a grid pattern or show up randomly after returning to the game.

    They just sit in stacks of 10 and only show 5 cubes in the scene.

    Any idea on where to go from here?
     
  12. ytwithlove

    ytwithlove

    Joined:
    Mar 14, 2013
    Posts:
    26
    Any ideas guys? Sadly haven't been able to make any progress.
     
  13. der_r

    der_r

    Joined:
    Mar 30, 2014
    Posts:
    259
    Can you give us a complete update on relevant code and scene setup?
     
  14. ytwithlove

    ytwithlove

    Joined:
    Mar 14, 2013
    Posts:
    26
    Sure thing!

    The scene is set up with a player capsule scripted to move on a plane. I have an empty game object holding 2 scripts: the Grid Instantiate script and the Respawn script. I have a cube prefab set up to be instantiated by the script.

    When the scene plays, the cube shows up in a 5 x 5 grid and the cubes can be picked up by the player. Once they are picked up, I have the script set to spawn a new cube after 1 second. I was hoping to have the cube spawn in the same place it was in the grid, but it doesn't.

    The cubes spawn, but in 5 separate places with 10 cubes placed in one spot, making it look like there is only 1 cube in the scene. When you pick up this cube, it picks up all 10 cubes in the same place and respawns all 10 in the same place.

    My goal is to get the cubes to either spawn back in the grid position or to spawn in random places on the stage.

    Here's my most current code:
    Player:
    Code (CSharp):
    1. public class Player : MonoBehaviour
    2. {
    3.     public float movementSpeed = 5.0f;
    4.     CharacterController character;
    5.  
    6.  
    7.     public GameObject prefab;
    8.     public int numberOfObjects = 5;
    9.     public float radius = 5f;
    10.    
    11.     bool PickedUp = false;
    12.  
    13.     // Use this for initialization
    14.     void Start ()
    15.     {
    16.  
    17.     }
    18.  
    19.     // Update is called once per frame
    20.     void Update ()
    21.     {
    22.         //Get the Character Controller//
    23.         CharacterController character = GetComponent<CharacterController>();
    24.  
    25.         //Character Movement//
    26.         float FBSpeed = Input.GetAxis("Vertical") * movementSpeed; //forward and back movement
    27.         float LRSpeed = Input.GetAxis("Horizontal") * movementSpeed; //left and right movement
    28.  
    29.         Vector3 speed = new Vector3(LRSpeed, 0, FBSpeed); //get the Vector for the speed
    30.         speed = transform.rotation * speed;  //storing the speed
    31.         character.Move(speed * Time.deltaTime); //get the character movement speed
    32.  
    33.     }
    34.    
    35.     void OnTriggerEnter(Collider other)
    36.     {
    37.         if (other.gameObject.tag =="Pickup")
    38.         {
    39.             PickedUp = true;
    40.             other.gameObject.SetActive(false);
    41.             StartCoroutine(RespawnItem());
    42.         }
    43.     }
    44.  
    45.     IEnumerator RespawnItem ()
    46.     {
    47.         if(PickedUp)
    48.         {
    49.             PickedUp = true;
    50.             int respawnTime = 1;
    51.             yield return new WaitForSeconds(respawnTime);
    52.             for (int i = 0; i < numberOfObjects; i++)
    53.             {
    54.                 float angle = i * Mathf.PI * 2 / numberOfObjects;
    55.                 Vector3 pos = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius;
    56.                 Instantiate(prefab, pos, Quaternion.identity);
    57.             }
    58.             Debug.Log ("Spawned!");
    59.         }
    60.         PickedUp = false;
    61.     }
    62. }
    63.  
    64.  
    Pickup:
    Code (CSharp):
    1. public class Pickup : MonoBehaviour
    2. {
    3.  
    4.     void OnTriggerEnter(Collider other)
    5.     {
    6.         if(other.gameObject.tag =="Pickup")
    7.         {
    8.             Destroy(other);
    9.         }
    10.     }
    11. }
    Grid setup:
    Code (CSharp):
    1. public class GridInstantiate : MonoBehaviour
    2. {
    3.     public GameObject prefab;
    4.     public float gridX = 5f;
    5.     public float gridY = 5f;
    6.     public float spacing = 2f;
    7.  
    8.     void Start() {
    9.         for (int y = 0; y < gridY; y++) {
    10.             for (int x = 0; x < gridX; x++) {
    11.                 Vector3 pos = new Vector3(x, 0, y) * spacing;
    12.                 Instantiate(prefab, pos, Quaternion.identity);
    13.             }
    14.         }
    15.     }
    16. }
    Circle setup (for testing to make sure I did the instantiate correctly)
    Code (CSharp):
    1. public class CircleInstantiate : MonoBehaviour {
    2.     public GameObject prefab;
    3.     public int numberOfObjects = 20;
    4.     public float radius = 5f;
    5.  
    6.     void Start() {
    7.         for (int i = 0; i < numberOfObjects; i++) {
    8.             float angle = i * Mathf.PI * 2 / numberOfObjects;
    9.             Vector3 pos = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius;
    10.             Instantiate(prefab, pos, Quaternion.identity);
    11.         }
    12.     }
    13.  
    14.     // Update is called once per frame
    15.     void Update () {
    16.  
    17.     }
    18. }
    Respawn:
    Code (CSharp):
    1. public class Respawn : MonoBehaviour
    2. {
    3.     public GameObject prefab;
    4.     public int numberOfObjects = 5;
    5.     public float radius = 5f;
    6.     bool PickedUp = false;
    7.  
    8.     void OnTriggerEnter(Collider other)
    9.     {
    10.         if (other.gameObject.tag =="Pickup")
    11.         {
    12.             other.gameObject.SetActive(false);
    13.             StartCoroutine(RespawnItem());
    14.         }
    15.     }
    16.  
    17.     IEnumerator RespawnItem ()
    18.     {
    19.         if(PickedUp)
    20.         {
    21.             PickedUp = true;
    22.             int respawnTime = 1;
    23.             yield return new WaitForSeconds(respawnTime);
    24.             for (int i = 0; i < numberOfObjects; i++)
    25.             {
    26.                 float angle = i * Mathf.PI * 2 / numberOfObjects;
    27.                 Vector3 pos = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius;
    28.                 Instantiate(prefab, pos, Quaternion.identity);
    29.             }
    30.             Debug.Log ("Spawned!");
    31.         }
    32.      
    33.         PickedUp = false;
    34.     }
    35. }
     
  15. der_r

    der_r

    Joined:
    Mar 30, 2014
    Posts:
    259
    I'm not sure I understand the purpose of the respawning code being there 2 times, once in the player script and once in the respawn script. They seem to be identical.

    And can you upload a web player? It might help us visualize the problem better. I'm lost right now. :D
     
  16. ytwithlove

    ytwithlove

    Joined:
    Mar 14, 2013
    Posts:
    26
    No problem! Sorry this is so confusing. I think I've been looking at this code for so long it's just melded together into one giant mess. Here's a link to the web player of the current build. Hopefully this will help visualize what I'm talking about. The cubes do generate all 10 in one place after they spawn. Really have no idea why that is. I make the strangest bugs occur in my games.

    https://db.tt/mpQ5fOBn
     
  17. ytwithlove

    ytwithlove

    Joined:
    Mar 14, 2013
    Posts:
    26
    Got some extra help from der_r (thank you!) and was able to get things working! Here's the code that works in case anyone else runs into this problem. Thank you everyone for your help! I really appreciate it! ^_^

    Player:
    Code (CSharp):
    1. public class Player : MonoBehaviour
    2. {
    3.     public float movementSpeed = 5.0f;
    4.     CharacterController character;
    5.  
    6.  
    7.     public GameObject prefab;
    8.     public float positionX = 3f;
    9.     public float positionY = 3f;
    10.    
    11.     bool PickedUp = false;
    12.    
    13.     // Update is called once per frame
    14.     void Update ()
    15.     {
    16.         //Get the Character Controller//
    17.         CharacterController character = GetComponent<CharacterController>();
    18.  
    19.         //Character Movement//
    20.         float FBSpeed = Input.GetAxis("Vertical") * movementSpeed; //forward and back movement
    21.         float LRSpeed = Input.GetAxis("Horizontal") * movementSpeed; //left and right movement
    22.  
    23.         Vector3 speed = new Vector3(LRSpeed, 0, FBSpeed); //get the Vector for the speed
    24.         speed = transform.rotation * speed;  //storing the speed
    25.         character.Move(speed * Time.deltaTime); //get the character movement speed
    26.  
    27.     }
    28.    
    29.     void OnTriggerEnter(Collider other)
    30.     {
    31.         if (other.gameObject.tag =="Pickup")
    32.         {
    33.             PickedUp = true;
    34.             other.gameObject.SetActive(false);
    35.             Invoke("RandomCube", 3);
    36.         }
    37.     }
    38.    
    39.     void RandomCube()
    40.     {
    41.         Vector3 position = new Vector3(Random.Range(-5.0F, 5.0F), 0, Random.Range(-5.0F, 5.0F));
    42.         Instantiate(prefab, position, Quaternion.identity);
    43.     }
    44. }