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

Starting a coroutine periodicaly.[Solved]

Discussion in '2D' started by Browdaddy96, Jan 1, 2016.

  1. Browdaddy96

    Browdaddy96

    Joined:
    Aug 27, 2015
    Posts:
    82
    So I am creating a top down 2D game(think the original Legend of Zelda) and I have these enemy spawners and I want them to wait a specific amount of time and then spawn an enemy then do it again. My problem is that I only want the enemies to spawn when the player is within 15 units of the spawner, if the player starts within 15 units of the spawner then it works until the player walks more then 15 units away then it doesn't work again.

    Here is the spawning script:

    Code (CSharp):
    1. public Transform[] enemies;
    2.     bool enemyOne = true;
    3.     public float waitTime = 3;
    4.     int enemy;
    5.     LevelGen levelGen;
    6.     public Transform player;
    7.     public LayerMask playerMask;
    8.     RaycastHit2D hit;
    9.  
    10.     void Start()
    11.     {
    12.         levelGen = GameObject.FindGameObjectWithTag("LevelGen").GetComponent<LevelGen>();
    13.  
    14.         enemy = Random.Range(0, enemies.Length);
    15.         if (enemies.Length == 1)
    16.         {
    17.             enemyOne = true;
    18.         } else
    19.         {
    20.             enemyOne = false;
    21.         }
    22.         StartCoroutine(CheckPlayerDistance());
    23.     }
    24.  
    25.     void Update()
    26.     {
    27.         if(player == null)
    28.         {
    29.             FindPlayer();
    30.         } else
    31.         {
    32.             Ray ray = new Ray(transform.position, player.position - transform.position);
    33.             float distRemaining = (Mathf.Sqrt((Mathf.Pow(player.position.x - transform.position.x, 2) + (Mathf.Pow(player.position.y - transform.position.y, 2)))));
    34.             hit = Physics2D.Raycast(transform.position, player.position - transform.position, distRemaining, playerMask);
    35.             Debug.DrawRay(transform.position, player.position - transform.position, Color.blue);
    36.             print(hit.distance);
    37.         }
    38.     }
    39.  
    40.     IEnumerator CheckPlayerDistance()
    41.     {
    42.         enemy = Random.Range(0, enemies.Length);
    43.         if (hit.distance <= 15)
    44.         {
    45.             StartCoroutine(SpawnEnemy(enemy));
    46.         }
    47.         StartCoroutine(CheckPlayerDistance());
    48.         yield return new WaitForSeconds(waitTime);
    49.     }
    50.  
    51.     public IEnumerator SpawnEnemy(int enemy)
    52.     {
    53.         enemy = Random.Range(0, enemies.Length);
    54.         if (enemyOne)
    55.         {
    56.             Instantiate(enemies[0], new Vector3(transform.position.x, transform.position.y, -1), transform.rotation);
    57.         }
    58.         else
    59.         {
    60.             Instantiate(enemies[enemy], new Vector3(transform.position.x, transform.position.y, -1), transform.rotation);
    61.         }
    62.  
    63.         yield return new WaitForSeconds(waitTime);
    64.        
    65.         StartCoroutine(CheckPlayerDistance());
    66.     }
    67.  
    68.     void FindPlayer()
    69.     {
    70.         if (levelGen.doneGenerating)
    71.         {
    72.             Transform _player = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
    73.             if (_player != null)
    74.             {
    75.                 player = _player;
    76.             }
    77.         }
    78.     }
    Thank you! Happy New Year :D
     
  2. Browdaddy96

    Browdaddy96

    Joined:
    Aug 27, 2015
    Posts:
    82
    He is the fixed script if you have a similar problem :p
    I was calling the CheckDistance method an infinite amount of times.

    Code (CSharp):
    1. public Transform[] enemies;
    2.     bool enemyOne = true;
    3.     public float waitTime = 3;
    4.     int enemy;
    5.     LevelGen levelGen;
    6.     public Transform player;
    7.     public LayerMask playerMask;
    8.     RaycastHit2D hit;
    9.  
    10.     void Start()
    11.     {
    12.         levelGen = GameObject.FindGameObjectWithTag("LevelGen").GetComponent<LevelGen>();
    13.  
    14.         enemy = Random.Range(0, enemies.Length);
    15.         if (enemies.Length == 1)
    16.         {
    17.             enemyOne = true;
    18.         } else
    19.         {
    20.             enemyOne = false;
    21.         }
    22.         StartCoroutine(CheckPlayerDistance());
    23.     }
    24.  
    25.     void Update()
    26.     {
    27.         if(player == null)
    28.         {
    29.             FindPlayer();
    30.         } else
    31.         {
    32.             Ray ray = new Ray(transform.position, player.position - transform.position);
    33.             float distRemaining = (Mathf.Sqrt((Mathf.Pow(player.position.x - transform.position.x, 2) + (Mathf.Pow(player.position.y - transform.position.y, 2)))));
    34.             hit = Physics2D.Raycast(transform.position, player.position - transform.position, distRemaining, playerMask);
    35.             Debug.DrawRay(transform.position, player.position - transform.position, Color.blue);
    36.         }
    37.     }
    38.  
    39.     IEnumerator CheckPlayerDistance()
    40.     {
    41.         enemy = Random.Range(0, enemies.Length);
    42.         print(hit.distance);
    43.         if (hit.distance <= 15)
    44.         {
    45.             StartCoroutine(SpawnEnemy(enemy));
    46.         }
    47.         yield return new WaitForSeconds(waitTime);
    48.         StartCoroutine(CheckPlayerDistance());
    49.     }
    50.  
    51.     public IEnumerator SpawnEnemy(int enemy)
    52.     {
    53.         enemy = Random.Range(0, enemies.Length);
    54.         if (enemyOne)
    55.         {
    56.             Instantiate(enemies[0], new Vector3(transform.position.x, transform.position.y, -1), transform.rotation);
    57.         }
    58.         else
    59.         {
    60.             Instantiate(enemies[enemy], new Vector3(transform.position.x, transform.position.y, -1), transform.rotation);
    61.         }
    62.  
    63.         yield return new WaitForSeconds(waitTime);
    64.        
    65.     }
    66.  
    67.     void FindPlayer()
    68.     {
    69.         if (levelGen.doneGenerating)
    70.         {
    71.             Transform _player = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
    72.             if (_player != null)
    73.             {
    74.                 player = _player;
    75.             }
    76.         }
    77.     }
     
  3. DuffyT

    DuffyT

    Joined:
    Dec 16, 2014
    Posts:
    37
    Just a bit of advice, comment your code, you'll make it alot easier for yourself (and those trying to understand your code).

    Now, I don't understand why you pass the random enemy from the first coroutine into the second if you're just going to take a new random? As I see your code, you can probably just put the code from the second coroutine into the first and let it run continuously (using while(true){}), ckecking the distance to each spawner and spawning (instantiating) enemies from those spawners that the player is close enough to.

    That way you don't have to start new coroutines from other coroutines which sometimes leads to infinite "coroutine-starting" and crashes Unity.

    Edit: seems the infinite coroutine thing was your problem :p
     
  4. Browdaddy96

    Browdaddy96

    Joined:
    Aug 27, 2015
    Posts:
    82
    It was, and since the issue(lets call it) I have optimized the script that script was more of a roof of concept that worked.