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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Remove array from spawn list

Discussion in 'Scripting' started by Frankzillaman, Jun 3, 2015.

  1. Frankzillaman

    Frankzillaman

    Joined:
    Mar 20, 2015
    Posts:
    22
    In my runner, i have multiple spawn triggers on the scene with a random array spawn.. Each trigger holds the same list of arrays, i do not want them to spawn over and over, i want the array removed from each list after it has spawned 1 time. Any ideas? Here is what i have so far for my spawn trigger.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. public class leveltrigger : MonoBehaviour {
    4.  
    5.  
    6.     bool hasSpawned = false;
    7.     public GameObject[] myObjects;
    8.     private GameObject myObject;
    9.    
    10.     void OnTriggerEnter(Collider col)
    11.     {
    12.         if (col.tag == "Player")
    13.         {
    14.             if (!hasSpawned)
    15.             {
    16.                 hasSpawned = true;
    17.                 Spawn ();
    18.             }
    19.         }
    20.     }
    21.    
    22.     void Spawn()
    23.     {
    24.         myObject = myObjects[Random.Range (0, myObjects.Length)];
    25.         Instantiate(myObject, new Vector3(transform.position.x + -.228f, transform.position.y + 1.90f, transform.position.z + -110.2f), Quaternion.identity);
    26.     }
    27. }
     
  2. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    Like so:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. public class LevelTrigger : MonoBehaviour {
    4.               //^ PascalCase class names
    5.              
    6.     bool hasSpawned = false;
    7.     //use a list instead of an Array. It's serializable, and it's length can
    8.     //be edited easily at runtime.
    9.     public List<GameObject> myObjects;
    10.    
    11.     //You don't need to declare myObject as a class member if you're only using it once
    12.     //private GameObject myObject;
    13.    
    14.     //Rather than having hardcoded values in your Spawn() method, I'd add a spawn offset variable.
    15.     //That way you can change it in the editor, and each level trigger could have a different spawn offset, if necessary.
    16.     public Vector3 spawnOffset = new Vector3(-0.228f, 1.9f, -110.2f);
    17.  
    18.     void OnTriggerEnter(Collider col)
    19.     {
    20.         //Add a check in here so that you don't try to spawn something if there is nothing left to spawn
    21.         if (col.tag == "Player" && !hasSpawned && myObjects.Count > 0) {
    22.             hasSpawned = true;
    23.             Spawn ();
    24.         }
    25.     }
    26.  
    27.     void Spawn()
    28.     {
    29.         int randomIndex = Random.Range (0, myObjects.Count);
    30.         GameObject myObject = myObjects[randomIndex];
    31.        
    32.         //Removes it from list, so it can't be spawned again.
    33.         myObjects.RemoveAt(randomIndex);
    34.        
    35.         Instantiate(myObject, transform.position + spawnOffset, Quaternion.identity);
    36.     }
    37. }
     
  3. Frankzillaman

    Frankzillaman

    Joined:
    Mar 20, 2015
    Posts:
    22
    @BenZed Wow thx buddy, works great only thing i cant get to come up is the hasSpawed in the inspector..Any ideas?
     
  4. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    if you want hasSpawned to be seen in the editor then:
    Code (CSharp):
    1. //either make it public
    2. public bool hasSpawned;
    3.  
    4. //or add the [SerializeField] attribute to it:
    5. [SerializeField] bool hasSpawned;
     
  5. Frankzillaman

    Frankzillaman

    Joined:
    Mar 20, 2015
    Posts:
    22
    @BenZed Appreicate it again man, so im running into the issue with my triggers.. So each trigger is duplicated with the same list.. Once the trigger is hit, the code works for that specific trigger and removes the object from the list.. Is there something i need to do , to have it work for all triggers? Remove an object from the list of each trigger?
     
    Last edited: Jun 4, 2015
  6. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    That make things a touch more complex. You have a couple of options:

    1) use a static list. Since static fields can't be serialized (viewable in the inspector) you'll need to set what's in the list programatically:

    Code (CSharp):
    1. //Imagine these in the above example.
    2. static List<GameObject> myObjects; //static, not public
    3.  
    4. void Awake()
    5. {
    6.     if (myObjects == null) //so that it's only set once.
    7.     {
    8.         myObjects = new List<GameObject>();
    9.         //We'll load them from your Resources folder, which will contain a bunch of MyObject prefabs
    10.         myObjects.AddRange(Resources.LoadAll<GameObject>("MyObjects");  
    11.     }
    12.      
    13. }
    2) use a serialized list in a gameManager object, and have each of your levelTriggers reference that list through a property.
    Code (CSharp):
    1. List<GameObject> myObjects {
    2.     get {
    3.         return GameManager.instance.myObjects;
    4.     }
    5. }
    6.  
    7. //and your game manager would be a singleton
    8.  
    9. public class GameManager : MonoBehaviour {
    10.  
    11.     public List<GameObject> myObjects; //here's the list you set.
    12.  
    13.     //EXTREMELY lazy singleton. If I were you I'd learn how to make them properly.
    14.     static _instance;
    15.     public static GameManager instance {
    16.         get {
    17.             return _instance;
    18.         }
    19.     }
    20.  
    21.     void Awake()
    22.     {
    23.         if (_instance)
    24.             throw new Error("Only one GameManager should every exist at a time!")
    25.         else
    26.             _instance = this;
    27.     }
    28. }
     
  7. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    I should point out when I mean singleton, I mean a Unity Psuedo singleton, not a real one. Look up Unity Singleton, or check my post history.
     
  8. Frankzillaman

    Frankzillaman

    Joined:
    Mar 20, 2015
    Posts:
    22
    @BenZed cool thx again, this sounds interesting. Definitely going to look into these methods. Also any suggestions, other than multiple triggers to spawn on certain points? to make life easier?
     
  9. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    I think the first option I gave you is the easiest.
     
  10. Frankzillaman

    Frankzillaman

    Joined:
    Mar 20, 2015
    Posts:
    22
    @BenZed so just a static list for each trigger?
     
  11. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    So long as every trigger uses your LevelTrigger class, the static list will have the same value.

    That's what a static variable means. It's attached to the class, not instances of it.