Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Gameobjects not spawning after i destroy them (Unity)

Im trying to make a first version of a game with unity, but the trees wont keep spawning after i have destroyed the tree amount to less than 5. In unity when i run the game it displays the tree amount and when it reaches 5 it stops spawning them but if i destroy one it wont spawn a new one even tho the tree amount is less than 5.

Also if i keep destroying them so there is always just two trees then it keeps spawning. But whenever it reaches 5 then it stops.

I have two scripts:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

This is the one where if i click the tree it destroys it.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Harvest : MonoBehaviour
{
    public GameObject tree;
    public int treeScore;
    public void AddTreeScore()
    {
        treeScore++;
    }

    private Spawner spawnerScript;
    void Start()
    {
        spawnerScript = FindObjectOfType<Spawner>();
    }

    public void OnMouseDown()
    {
        GameObject.Destroy(tree);
        spawnerScript.treeAmount--;
        AddTreeScore();
        Debug.Log(treeScore);
        

    }


}

And this is everything else.

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class Spawner : MonoBehaviour
{
    public GameObject tree;

    public int treeAmount;

    public float spawnRate = 1f;

    public bool canSpawn = true;

    public int maxAmount = 5;

    private IEnumerator Spawning()
    {
        WaitForSeconds wait = new WaitForSeconds(spawnRate);

        while (canSpawn == true)
        {
            yield return wait;
            
            Vector2 randomSpawnPos = new Vector2(Random.Range(-10, 11), Random.Range(-4, 5));
            Instantiate(tree, randomSpawnPos, Quaternion.identity);
            AddTreeAmount();

            if (treeAmount >= maxAmount)
            {
                canSpawn = false;
                
            }
            if( treeAmount < maxAmount)
            {
                canSpawn = true;
            }
            

        }
    }
    void AddTreeAmount()
    {
        treeAmount++;
    }

    void Start()
    {
        StartCoroutine(Spawning());
    }

    void Update()
    {
        
    }
}

I also tried setting the spawnRate to 0f; and then back to 1f;, but that did not work. It showed in unity that the spawnRate went to 0 but it kept still spawning them.

I think i have to set the canSpawn back to true some other way. Or is there more errors or mistakes?

>Solution :

Your coroutine Spawning runs exactly once – at the beginning of the game.

void Start()
{
    StartCoroutine(Spawning());
}

Once canSpawn = false; is reached it will never run again.

Instead you could use a field for tracking if an instance of that routine is already running and if not run a new one like e.g.

public class Spawner : MonoBehaviour
{
    // in general for things you only set up via the Inspector
    // you should use private o avoid other classes to modify them (Encapsulation)
    [SerializeField] private GameObject tree;
    [SerializeField] private float spawnRate = 1f;
    [SerializeField] private int maxAmount = 5;

    // backing field for treeAmount
    private int _treeAmount;

    // keeps track whether a Spawning routine is already running
    private bool spawning;

    public int treeAmount
    {
        get => _treeAmount;
        set 
        {
            // this is executed whenever a value is assigned

            _treeAmount = value;
            RunSpawningRoutine();
        }
    }

    private void Start()
    {
         RunSpawningRoutine();
    }

    private void RunSpawningRoutine()
    {
        // if already spawning ignore
        if(spawning) return;

        StartCoroutine(Spawning());
    }

    private IEnumerator Spawning()
    {
        // just in case double safety for blocking concurrent routines
        if(spawning) yield break;

        // block other routines from running (see above)
        spawning = true;

        // simpler and cleaner loop condition
        while (treeAmount < maxAmount)
        {
            yield return new WaitForSeconds(spawnRate);
            
            // generally note that this does not prevent two trees spawning in the same spot
            var randomSpawnPos = new Vector2(Random.Range(-10, 11), Random.Range(-4, 5));
            Instantiate(tree, randomSpawnPos, Quaternion.identity);
            treeAmount++;
        }

        // allow a next routine to start
        spawning = false;
    }
}

This way whenever a value is assigned to treeAmount it will kickoff RunSpawningRoutine. Here you will check whether a routine is already running in which case you don’t have to do anything, but if not it will start a new routine.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading