Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by GregoryNeal · Jan 12, 2014 at 12:49 AM · c#scripting problemaienemy

Enemy Spawn Script Spawning Infinite Enemies [Help]

I'm trying to test my enemy spawn script (c#), and I thought I had it pretty well figured out. For the meantime it's all attached to my enemy prefab, but eventually I will attach it to the player. This is how the script is supposed to work:

  1. In the start function, check how many objects have the tag "Enemy".

  2. If it's greater than 0 (for testing) run the StartLevel function, passing a levelIndex variable.

  3. In StartLevel, do some things (not implemented), then call SpawnEnemy, passing the number of enemies to spawn.

  4. In SpawnEnemy, for each enemy that needs to be spawned, find a random point around the player (x,z), then pass that point to a function that finds the terrain height at this point. If it returns a valid number, and passes some other conditions (isn't too close to player, or too close to other spawned enemies) spawn this enemy, facing the player.

  5. Save this spawn point as the lastSpawnPoint for any other enemies that need spawning.

Here is the relevant code:

  using UnityEngine;
     using System.Collections;
     
     public class EnemyScript : MonoBehaviour {
     
         public Transform playerPos;
         public float enemySpeed = 5f;
         public float detectionRadius = 150;
         public CharacterController cc;
         public GameObject enemyPrefab;
         public bool sawPlayer = false;
         public Vector3 playerDirection = Vector3.zero;
         public float verticalSpeed;
         public float spawnDistance = 50.0f;
         public float minEnemySpawnDensity = 6f;
         public float minSpawnDistance = 20f;
         public int spawnThisMany = 0;
     
     
         // Use this for initialization
         void Start () {
 
                 //get the transform of the player
             playerPos = GameObject.FindWithTag("Player").transform;
 
                 //get the character controller attached to the enemyPrefab
             cc.GetComponent<CharacterController>();
 
                 //if there are no enemies present, start level 1
             if(GameObject.FindGameObjectsWithTag("Enemy").Length >= 0){
                 StartLevel(spawnThisMany);
             }
     
         }
     
         //this function handles the spawning of enemies around you. It is called
         //from the startLevel function, which handles the number of enemies in 
         //each level.
         void SpawnEnemy(int numberOfEnemies){
 
                 //find a random point around the player
             Vector3 spawnPoint = Random.insideUnitCircle.normalized*spawnDistance;
             Vector3 lastSpawnPoint = Vector3.zero;
 
                 //this sets the spawn point height to the terrain height, plus a the radius of the sphere's character controller
             spawnPoint.y = TerrainHeight(spawnPoint) + cc.radius;
 
                 for(int enemyCount = 0; enemyCount < numberOfEnemies; enemyCount++){
 
                         //if terrain height returns infinity, or the difference in this spawn
                 //point and the last spawn point is greater than the minimus spawn
                 //density, or the enemy spawns to close to the player, start over.
                 if(spawnPoint.y == Mathf.Infinity || (spawnPoint - lastSpawnPoint).magnitude <= minEnemySpawnDensity || (spawnPoint - playerPos.position).magnitude <= minSpawnDistance){
                     SpawnEnemy(numberOfEnemies - enemyCount);
                 }
 
                         //if all the conditions are met, an enemy is spawned facing the player,
                 //and the spawn point is saved as the last spawn point.
                 else{
                     //setting look direction for enemy, cancelling out the y portion
                     Vector3 lookDirection = playerPos.position;
                     lookDirection.y = 0f;
                     Instantiate(enemyPrefab,spawnPoint,Quaternion.LookRotation(lookDirection));
                     lastSpawnPoint = spawnPoint;
                 }
             }
     
         }
 
         //this starts each level
         void StartLevel(int levelIndex){
                 //do stuff here
             SpawnEnemy (levelIndex);
         }
 
         //TerrainHeight finds the height of the terrain given a 2D position vector
         float TerrainHeight(Vector2 spawnPoint){
 
             //declare a raycast hitpoint
             RaycastHit hitPoint;
 
             //go to spawnPoint and cast a ray upwards, if it hits return that y position.
             //if it doesn't, shoot a ray downwards and it should hit, if not, return infinity.
             if(Physics.Raycast(spawnPoint,Vector3.up, out hitPoint)){
                 return hitPoint.transform.position.y;
             }
             else if(Physics.Raycast(spawnPoint,Vector3.down, out hitPoint)){
                 return hitPoint.transform.position.y;
             }
             else{
                 return Mathf.Infinity;
             }
         }
     }
     

I'm pretty sure the problem lies within my for statement, although for the life of me I can't figure it out. It's probably something silly. But everytime I go to play mode, the enemies just keep piling up and lagging my game. About 150 spawn before I can get out of play mode. Thanks for any help.

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image RyanPaterson · Jan 12, 2014 at 01:17 AM 0
Share

Where are you declaring the value of 'numberofenemies'?

avatar image GregoryNeal · Jan 12, 2014 at 01:26 AM 0
Share

It's passed as an integer into SpawnEnemy from StartLevel. I declared the integer spawnThis$$anonymous$$any, which is passed to StartLevel as the levelIndex, then levelIndex is passed to SpawnEnemy as numberOfEnemies. Yea, it's a bit convoluted at the moment. But eventually I'll do stuff in the startlevel method to calculate an actual number of enemies per level.

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by KellyThomas · Jan 12, 2014 at 02:18 AM

@Moohasha is correct in that every time you call recursively call SpawnEnemy you are going to double up on the remainder of your enemy spawns. The reason you will double up is that you are starting a new loop, and will (once it is finished) continue the old loop.

I would recommend an iterative rather than recursive approach:

     void SpawnEnemy(int numberOfEnemies) {
         Vector3 lastSpawnPoint = Vector3.zero;
         Vector3 spawnPoint = Vector3.zero;
         for(int enemyCount = 0; enemyCount < numberOfEnemies; enemyCount++){
             do {
                 spawnPoint = Random.insideUnitCircle.normalized * spawnDistance;
                 spawnPoint.y = TerrainHeight(spawnPoint) + cc.radius;
             } while(IsInvalidSpawnPoint(spawnPoint, lastSpawnPoint));
             
             Vector3 lookDirection = playerPos.position;
             lookDirection.y = 0f;
             Instantiate(enemyPrefab, spawnPoint, Quaternion.LookRotation(lookDirection));
             lastSpawnPoint = spawnPoint;
         }
     }

     boolean IsInvalidSpawnPoint(Vector3 spawnPoint,Vector3 lastSpawnPoint){
         return spawnPoint.y == Mathf.Infinity ||
                (spawnPoint - lastSpawnPoint).magnitude <= minEnemySpawnDensity ||
                (spawnPoint - playerPos.position).magnitude <= minSpawnDistance;
     }
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image GregoryNeal · Jan 12, 2014 at 02:52 AM 0
Share

Thank you for this. There were some errors in your code, as well some unwanted behaviour. For instance my raycast hit was returning the height of the terrain gameobject, and my enemies were spawning at world coords (0,0). But I managed to sort them out, and now it works perfectly, thanks you to and @$$anonymous$$oohasha.

avatar image KellyThomas · Jan 12, 2014 at 03:03 AM 0
Share

@GregoryNeal glad it hear it worked out. Without running it in the context of you project it's sure to have a few kinks.

avatar image DRRosen3 · Nov 22, 2014 at 05:43 PM 0
Share

I'm using this solution as a reference for my own Spawn$$anonymous$$anager class...but I'm having the same problem you had @GregoryNeal where all my enemies are spawning at (0,0). Can you help me out with the solution you found?

avatar image
1

Answer by Moohasha · Jan 12, 2014 at 01:22 AM

It looks like you accidentally set up a recursive method in SpawnEnemy. You pass in the number to spawn and use that in your for loop, but then call SpawnEnemy with the same number within the for loop. This will just keep going forever. Rather than having your for loop inside SpawnEnemy, have it outside, and have the methods only spawn one at a time.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image GregoryNeal · Jan 12, 2014 at 01:46 AM 0
Share

When I call SpawnEnemy recursively, I pass it the number of enemies - the number of spawned enemies. If the spawn is successful, it increases enemyCount, then loops, if it isn't successful, it calls SpawnEnemy(numberOfEnemies - enemyCount). I don't understand how that's the problem D:

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How do I get my emeny AI to detect if he sees a player, or one of the good AI? (C#) 3 Answers

If I duplicate enemies, will their scripts mess each other up? 2 Answers

Make player not be seen by AI, when player in foilage and shadows. 1 Answer

Make AI walk around randomly until Player is Seen. (C#) 2 Answers

The name 'Joystick' does not denote a valid type ('not found') 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges