Results 1 to 10 of 10
  1. #1
    Join Date
    Apr 2011
    Posts
    103

    Spawning a fixed amount of Enemies

    I have a simple enemy spawn script that spawns an infinite amount of enemies over time.
    How can I modify it so I can limit the amount of enemies that can spawn?

    Code:
    using UnityEngine;
    
    public class EnemyManager : MonoBehaviour
    {
    	public GameObject enemy;
    	public float startDelay = 5f;
    	public float spawnTime = 3f;
    	public float numOfEnemies = 5;
    	public Transform[] spawnPoints;
    
    	void Start ()
    	{
    		InvokeRepeating ("SpawnEnemey", startDelay, spawnTime);
    	}
    
    	void SpawnEnemey ()
    	{
    		int spawnPointIndex = Random.Range (0, spawnPoints.Length);
    
    		Instantiate (enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
    	}
    }

  2. #2
    Join Date
    Jul 2012
    Location
    Ankara, Turkey
    Posts
    98
    One way would be to make a list and put each enemy you make in it. Then you can check in SpawnEnemy that enemies are only instantiated when the list does not contain more than an x amount of members. Of course you also want to delete enemies from the list when they die, in order to keep the list up to date.

  3. #3
    Join Date
    Mar 2004
    Location
    Anacortes, WA
    Posts
    4,168
    An alternative way would be to create a component that looks something like:

    Code:
    using UnityEngine;
    
    public class EnemyCounter
    {
            private EnemyManager _manager;
    
            public void Init(EnemyManager manager)
            {
                _manager = manager;
            }
    
            public void OnDestroy()
            {
                _manager.OnEnemyDestroyed(this);
            }
    }
    Then modify your EnemyManager class like:

    Code:
    using UnityEngine;
    
    public class EnemyManager : MonoBehaviour
    {
    	public GameObject enemy;
    	public float startDelay = 5f;
    	public float spawnTime = 3f;
    	public float numOfEnemies = 5;
    	public Transform[] spawnPoints;
    
            private int _totalEnemyCount;
    
    	void Start ()
    	{
    		InvokeRepeating ("SpawnEnemey", startDelay, spawnTime);
    	}
    
    	void SpawnEnemey ()
    	{
                    if (_totalEnemyCount >= numOfEnemies)
                        return;
    
    		int spawnPointIndex = Random.Range (0, spawnPoints.Length);
    
    		var enemey = Instantiate (enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
                    enemy.AddComponent<EnemyCounter>().Init(this);
                    _totalEnemyCount++;
    	}
    
            public void OnEnemyDestroyed(EnemyCounter enemy)
            {
                    _totalEnemyCount--;
            }
    }
    That would do what you want it to
    Need any help? Feel free to PM me - or send an email directly to nelson@3dbuzz.com!

  4. #4
    Join Date
    Apr 2011
    Posts
    103
    Nelson I'm having a bit of trouble using your code. Using what you provided I get an error:
    Code:
    Assets/EnemyManager.cs(26,23): error CS0309: The type `EnemyCounter' must be convertible to `UnityEngine.Component' in order to use it as parameter `T' in the generic type or method `UnityEngine.GameObject.AddComponent<T>()'
    I added : MonoBehaviour to the script thinking components must be MonoBehaviours. It seems to work but every instantiated enemy looks something like this, enemy(Clone) 1 has no EnemyCounter component attached, enemy(Clone) 2 has 1 EnemyCounter component attached, enemy(Clone) 3 has 2 EnemyCounter components attached....etc, etc

    Upon stopping the game I get several
    Code:
    NullReferenceException: Object reference not set to an instance of an object
    EnemyCounter.OnDestroy () (at Assets/EnemyCounter.cs:14)
    My guess its due to all the extra components getting attached.

  5. #5
    Join Date
    Mar 2004
    Location
    Anacortes, WA
    Posts
    4,168
    Yeah, every C# component must inherit from MonoBehavior.

    As far as what you're seeing... That's odd. How many Enemy Managers do you have on your scene? Also, for the null reference exception, are you sure that enemy.AddComponent<EnemyCounter>().Init(this); is written properly?
    Need any help? Feel free to PM me - or send an email directly to nelson@3dbuzz.com!

  6. #6
    Join Date
    Apr 2011
    Posts
    103
    I only have one EnemyManager in the scene, attached to a gameobject named manager.
    As for the code I literally just copied what you posted and added the MonoBehavior part to EnemyCounter.

    Here is a unitypakage with everything set up if you want to look at it.

    Also here is a warning that slipped by me last time

    Code:
    Assets/EnemyManager.cs(25,21): warning CS0168: The variable `enemey' is declared but never used
    is that because “enemy” is not set until runtime?
    Last edited by PencilShavings; 03-17-2015 at 08:46 PM. Reason: removed link

  7. #7
    Join Date
    Mar 2004
    Location
    Anacortes, WA
    Posts
    4,168
    Wups... My bad again.

    Another spelling error. This:
    Code:
    		var enemey = Instantiate (enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
                    enemy.AddComponent<EnemyCounter>().Init(this);
    Should be
    Code:
    		var enemy = Instantiate (enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
                    enemy.AddComponent<EnemyCounter>().Init(this);
    What is happening is that there is a naming conflict. The local variable is named the same as your field (but the local variable name I wrote had a spelling error in it, so it didn't override the field). The code I posted was supposed to be invoking AddComponent on the local variable enemy (the object that was cloned into the scene) not the public field enemy (the prefab itself which lives in your assets folder).

    I would go ahead and rename your enemy public field to Enemy, as that is the C# naming standard for public fields. That way, local variables won't conflict with your class variables.

    Here's what happened: AddComponent was not being invoked on the object that was cloned. AddComponent was being invoked on the prefab itself - which means the asset itself was changed. Click on your enemy prefab in your project window. Notice how it has a ton of Enemy Counter objects on it. Go ahead and clear all of those out using the inspector, then fix the spelling error in the code.

    Now everything should work and sorry for the few spelling mistakes there. I was writing all of that code directly into the reply box.
    Need any help? Feel free to PM me - or send an email directly to nelson@3dbuzz.com!

  8. #8
    Join Date
    Apr 2011
    Posts
    103
    Ok so I renamed my public gameobject var to EnemyObject so I can see the difference more easily however now I get way more errors popping up for some reason.

    Updated the link above with a new unitypackage.

  9. #9
    Join Date
    Mar 2004
    Location
    Anacortes, WA
    Posts
    4,168
    Three issues:

    1) you have a 00 on line 13 that you need to remove
    2) you need to cast enemy to a GameObject to get access to the AddComponent method (another thing I overlooked). Do this by replacing line 25 with
    Code:
    ar enemy = (GameObject)Instantiate (EnemyObject, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
    3) your EnemyObject prefab lost its connection since you renamed it, you'll need to re-drag the npc prefab onto it

    Need any help? Feel free to PM me - or send an email directly to nelson@3dbuzz.com!

  10. #10
    Join Date
    Apr 2011
    Posts
    103
    00, well how did that get in there?

    One last thing. All the enemies spawn correctly now and when you delete one another one spawns back in its place. What needs to be modified to have no more enemies continuing to spawn at all after they are destroyed. So say 5 enemies are instantiated and then that’s it, when there are all destroyed the script is over.

    Anyway thanks for all help!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •