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();
}
}
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());
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.