'IEnumerator WaitForSeconds not working in Unity
I'm currently working on an ecosystem simulation project. The first mechanic I'm trying to work on is trees/plants spreading. I have a script that I attach to my tree that processes as follows:
(1) Check if tree is mature, if it is generateSpawner(); (2) !treeMature Grow (Not implemented yet, I just have bool treeMature = true)
(3) GenerateSpawner works by checking random coordinates in a circle around the tree for any pre-existing plants. If there is not a plant, the script generates a spawner, then waits for a 120 seconds before checking again.
(4) If there is a plant the program is supposed to wait 30 seconds then check another spot.
The issue lies in the wait portion. Both in the spawning portion and in the non-spawning portion. The script rapidly creates spawners, or if I don't allow the script to create spawners the script rapidly generates checks.
Here's the code, why isn't my IEnumerator working?
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlantAI : MonoBehaviour
{
public GameObject plantSpawn, thisPlant;
public LayerMask WhatIsPlant;
public Vector3 clearingCheck;
bool treeMature = true, plantAdjacent, isClearing;
public float spawnRange;
void Start()
{
if (treeMature) GenerateSpawner();
if (!treeMature) Grow();
}
void Update()
{
if (treeMature) GenerateSpawner();
if (!treeMature) Grow();
}
private void GenerateSpawner()
{
StartCoroutine(LookForClearing());
}
IEnumerator LookForClearing()
{
float deltaZ = UnityEngine.Random.Range(-spawnRange, spawnRange);
float deltaX = UnityEngine.Random.Range(-spawnRange, spawnRange);
clearingCheck = new Vector3(thisPlant.transform.position.x + deltaX, thisPlant.transform.position.y, thisPlant.transform.position.z + deltaZ);
plantAdjacent = Physics.CheckSphere(clearingCheck, spawnRange, WhatIsPlant);
if (!plantAdjacent) isClearing = true;
if (isClearing)
{
GameObject spawn = Instantiate(plantSpawn, thisPlant.transform.position, Quaternion.AngleAxis(UnityEngine.Random.Range(0, 359), Vector3.up));
isClearing = false;
yield return new WaitForSeconds(120);
}
if (!isClearing)
{
yield return new WaitForSeconds(30);
}
}
private void Grow()
{
throw new NotImplementedException();
}
}
Solution 1:[1]
It rapidly generate checks because GenerateSpawner() it's in the Update() and thus will trigger the coroutine. If you need to wait and start over, you can use a delegate to be called when completed.
Alternatively, you may want to not call the spawner, in the Update() and just in the Start().
Try modifying the spawner like this so it's waiting for the WaitForSeconds() to continue code execution.
IEnumerator LookForClearing()
{
float deltaZ = UnityEngine.Random.Range(-spawnRange, spawnRange);
float deltaX = UnityEngine.Random.Range(-spawnRange, spawnRange);
clearingCheck = new Vector3(thisPlant.transform.position.x + deltaX, thisPlant.transform.position.y, thisPlant.transform.position.z + deltaZ);
plantAdjacent = Physics.CheckSphere(clearingCheck, spawnRange, WhatIsPlant);
if (!plantAdjacent) isClearing = true;
if (isClearing)
{
yield return new WaitForSeconds(120.0f);
GameObject spawn = Instantiate(plantSpawn, thisPlant.transform.position, Quaternion.AngleAxis(UnityEngine.Random.Range(0, 359), Vector3.up));
isClearing = false;
Debug.Log("Spawn a plant!");
}
if (!isClearing)
{
yield return new WaitForSeconds(30.0f);
Debug.Log("Wait another 30s");
}
StartCoroutine(LookForClearing());
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dharman |
