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

Make Spawn script stop when a gameobject is visible by camera

Discussion in 'Scripting' started by Bloodember, Jun 13, 2015.

  1. Bloodember

    Bloodember

    Joined:
    Mar 30, 2014
    Posts:
    41
    The title says it all, I need the spawn script to stop spawning when a gameobject is on screen, the restart when gameobject is gone.

    I've tried multiple different ways and did tons of searching without any results. I could use some help.

    Here's the spawn script and what I have now, which is wrong since it doesn't work.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class SpawnScript : MonoBehaviour
    6. {
    7.    public Transform obj;
    8.    public int numobj;
    9.    public int minX, maxX;
    10.    public int minY, maxY;
    11.    public int minZ, maxZ;
    12.    public float spawnMin = 2f;
    13.    public float spawnMax = 5f;
    14.    public float waitStart;
    15.    public float spawnWait;
    16.  
    17.  
    18.    void Start()
    19.    {
    20.  
    21.      StartCoroutine (Spawn ());
    22.    }
    23.    void Update()
    24.    {
    25.  
    26.    }
    27.    public IEnumerator Spawn()
    28.    {
    29.      yield return new WaitForSeconds (waitStart);
    30.      while (true) {
    31.        for (int i = 0; i < numobj; i++) {
    32.          Instantiate (obj, GeneratedPosition (), Quaternion.identity);
    33.          yield return new WaitForSeconds (spawnWait);
    34.        }
    35.        yield return new WaitForSeconds (waitStart);
    36.      }
    37.  
    38.      //Invoke ("Spawn", Random.Range (spawnMin, spawnMax));
    39.    }
    40.    Vector3 GeneratedPosition()
    41.    {
    42.      int x, y, z;
    43.      x = UnityEngine.Random.Range (minX, maxX);
    44.      y = UnityEngine.Random.Range (minY, maxY);
    45.      z = UnityEngine.Random.Range (minZ, maxZ);
    46.      return new Vector3 (x, y, z);
    47.    }
    48.  
    49.    public void OnBecameVisible()
    50.    {
    51.      if (gameObject.tag == "Boss")
    52.      {
    53.        StopCoroutine (Spawn ());
    54.      }
    55.    }
    56.    void OnBecameInVisible(Collider2D other)
    57.    {
    58.      if (other.tag == "Boss") {
    59.        StartCoroutine (Spawn ());
    60.      }
    61.    }
    62. }
    63.  
    Thank you for any help.
     
  2. Duugu

    Duugu

    Joined:
    May 23, 2015
    Posts:
    241
    So, do the events trigger, or is the coroutine the problem?
    Do you use more than one camera?

    [e]
    Oh, OnBecameInVisible is private. Try to declare it as public.
     
  3. PGJ

    PGJ

    Joined:
    Jan 21, 2014
    Posts:
    897
    OnBecomeVisible is called when an object's renderer is visible to the camera. So it is valid only for the object to which the script is attached. Since this is you spawner script, it will always refer to the spawner and nothing else.

    Here's quick and dirty way to check if something is on screen;
    Code (CSharp):
    1.  
    2. public LayerMask bossLayer;
    3.  
    4.     void Update ()
    5.     {
    6.         // The boundries of the camera
    7.         Vector2 point1 = Camera.main.ViewportToWorldPoint(Vector2.zero);
    8.         Vector2 point2 = Camera.main.ViewportToWorldPoint(Vector2.one);
    9.  
    10.         Collider2D onScreen = Physics2D.OverlapArea(point1,point2,bossLayer);
    11.  
    12.         if (onScreen)
    13.         {
    14.             Debug.Log("Shown");
    15.         }
    16.         else
    17.         {
    18.             Debug.Log(" Not shown");
    19.            
    20.         }
    21.     }
    As you can see, this uses a layer to separate which objects should be checked. So you need to define a boss layer and add that layer to your boss. Also you need to set the public LayerMask to the correct layer.
     
  4. Bloodember

    Bloodember

    Joined:
    Mar 30, 2014
    Posts:
    41
    PGJ,

    I've added your code and it shows it's working, but it's not stopping the Coroutine. I've used the StopCoroutin (Spawn()) and the way it's in the code, it doesn't work. The debug.log is working so I know it's working.

    Here's the code.
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class SpawnScript : MonoBehaviour
    6. {
    7.    public Transform obj;
    8.    public int numobj;
    9.    public int minX, maxX;
    10.    public int minY, maxY;
    11.    public int minZ, maxZ;
    12.    public float spawnMin = 2f;
    13.    public float spawnMax = 5f;
    14.    public float waitStart;
    15.    public float spawnWait;
    16.  
    17.    public LayerMask bossLayer;
    18.    void Start()
    19.    {
    20.  
    21.      StartCoroutine (Spawn ());
    22.    }
    23.    void Update()
    24.    {
    25.      Vector2 point1 = Camera.main.ViewportToWorldPoint (Vector2.zero);
    26.      Vector2 point2 = Camera.main.ViewportToWorldPoint (Vector2.one);
    27.  
    28.      Collider2D onScreen = Physics2D.OverlapArea (point1, point2, bossLayer);
    29.  
    30.      if (onScreen) {
    31.        StopCoroutine ("Spawn");
    32.        Debug.Log ("StopCoroutine");
    33.      } else
    34.      {
    35.        //StartCoroutine (Spawn ());
    36.        Debug.Log ("StartCoroutine");
    37.      }
    38.    }
    39.    public IEnumerator Spawn()
    40.    {
    41.      yield return new WaitForSeconds (waitStart);
    42.      while (true) {
    43.        for (int i = 0; i < numobj; i++) {
    44.          Instantiate (obj, GeneratedPosition (), Quaternion.identity);
    45.          yield return new WaitForSeconds (spawnWait);
    46.        }
    47.        yield return new WaitForSeconds (waitStart);
    48.      }
    49.  
    50.      //Invoke ("Spawn", Random.Range (spawnMin, spawnMax));
    51.    }
    52.    Vector3 GeneratedPosition()
    53.    {
    54.      int x, y, z;
    55.      x = UnityEngine.Random.Range (minX, maxX);
    56.      y = UnityEngine.Random.Range (minY, maxY);
    57.      z = UnityEngine.Random.Range (minZ, maxZ);
    58.      return new Vector3 (x, y, z);
    59.    }
    60.  
    61.  
    62. }
    63.  
    64.  
    Also I can't restart the coroutine using update, it causes hundreds of objects to spawn.
     
  5. PGJ

    PGJ

    Joined:
    Jan 21, 2014
    Posts:
    897
    If I remember correctly you need to use the string version of StartCoroutine to be able to use StopCoroutine. So try changing to:
    Code (CSharp):
    1.  
    2. StartCoroutine("Spawn");
    3.  
    Also, are you sure you want to run several instances of Spawn at the same time? Each time you run StartCoroutine you will start a new instance of Spawn (that is if you uncomment line 35). You might want to check if it is already running and only start if it isn't...
     
  6. Bloodember

    Bloodember

    Joined:
    Mar 30, 2014
    Posts:
    41
    That worked, it stopped. Now I don't want to start several instances of Spawn that's why it's blocked out. I just want to restart the ones that I stopped. So how do I get my spawners to restart?
     
  7. lordconstant

    lordconstant

    Joined:
    Jul 4, 2013
    Posts:
    389
    Add a bool called spawning and set it to false when you stop, true when you start then just check if it is false before starting.
     
  8. Bloodember

    Bloodember

    Joined:
    Mar 30, 2014
    Posts:
    41
    Thank you that worked.