Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Best way to initiate objects for an endless runner? My coroutine seems to be messed up

Discussion in 'Scripting' started by Chris75, Jun 18, 2016.

  1. Chris75

    Chris75

    Joined:
    Jan 31, 2015
    Posts:
    41
    Hey all. Will make this short. Working on my first game as a basic endless runner, just to get my hands on things.

    For my game, objects spawn faster as the player's score increases.

    Here is my coroutine code (just a snippet):

    Code (csharp):
    1.  IEnumerator SpawnObject(int index, float seconds)
    2.   {
    3.  yield return new WaitForSeconds(seconds);
    4.  Instantiate(enemies[index], enemies[index].transform.position, enemies[index].transform.rotation);
    5.  
    6.   isSpawning = false;
    7. }
    8.  
    9. else if (!isSpawning && isDead == 0 && score >= 6)
    10.   {
    11.   isSpawning = true;
    12.   int enemyIndex = Random.Range(0, enemies.Length);
    13.   StartCoroutine(SpawnObject(enemyIndex, Random.Range(0.95f, 0.95f)));
    14.   }
    The speed of the objects also increases as the player's score goes up. Here is a sample code:

    Code (csharp):
    1.  
    2. else if (score >= 6)
    3.   {
    4.   transform.Translate(-9 * Time.deltaTime, 0, 0);
    5.   }
    The above setup is just a snippet of my code where if the player score is greater than or equal to 6, the movement of objects is -9 and they spawn every .95f of a second. As the player's score increases, so do both settings all the way up to .35f to -23 speed.

    So my issue is, is that with this current set up, the game objects do not spawn properly. For example, when each object is to spawn at .95f seconds, the distance between each object is different. While not by a lot, enough where it affects the game.

    I posted this help issue on Reddit only to get insulted for not knowing how to do this properly. But he did vaguely say I should spawn them during the same frame. Not sure what that means exactly.

    Any help would be greatly appreciated on how to better spawn my objects or what is wrong with my code where the objects are not spawning at the time I listed.

    I know there is an issue because I tested my scene with the above code only and the objects would spawn at different distances. I included an example of how I could tell (my cheap way of seeing the distance was to use a sprite). So as you can see, despite them being set to spawn .95f of a second the entire scene, some are spawning different as there is a larger gap:


     
  2. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Are you not using a fixed spawn location for your objects? The easiest way to do this would be to skip using co-routines altogether(mainly because they suck:mad:).

    Code (CSharp):
    1. public class ObstacleSpawner : MonoBehaviour
    2. {
    3.    public HashSet<GameObject> SpawnedObstacles = new HashSet<GameObject>();
    4.  
    5.    public GameObject[] ObstaclePrefabs;
    6.    public Transform SpawnPosition;
    7.    public float SpawnRate;
    8.    public float LastSpawn;
    9.  
    10.    void Update()
    11.    {
    12.      if (ObstaclePrefabs == null || ObstaclePrefabs.Length < 1) return;
    13.  
    14.      if ((Time.time - SpawnRate) > LastSpawn)
    15.      {
    16.        //pick a random obstacle to spawn
    17.        int obstacleIndex = Random.Range(0, ObstaclePrefabs.Length);
    18.  
    19.        //instantiate the obstacle at the spawn position
    20.        GameObject obstacle = Instantiate(ObstaclePrefabs[obstacleIndex], SpawnPosition.position, SpawnPosition.rotation) as GameObject;
    21.        if (obstacle != null)
    22.        {
    23.          //add the obstacle to our spawned set
    24.          SpawnedObstacles.Add(obstacle);
    25.  
    26.          ObstacleMovementController mover = obstacle.GetComponent<ObstacleMovementController>();
    27.          if (mover != null)
    28.          {
    29.            //inject the spawner into the movement controller
    30.            mover.Spawner = this;
    31.          }
    32.        }
    33.        LastSpawn = Time.time;
    34.      }
    35.    }
    36.  
    37.    public void RemoveObstacle(GameObject pObstacle)
    38.    {
    39.      SpawnedObstacles.Remove(pObstacle);
    40.    }
    41.  
    42.    public void UpdateSpawnRate(float pScore)
    43.    {
    44.      //update spawn rate based on score
    45.  
    46.      //update all our obstacles with the new score as well
    47.      foreach (GameObject obstacle in SpawnedObstacles)
    48.      {
    49.        ObstacleMovementController mover = obstacle.GetComponent<ObstacleMovementController>();
    50.        if (mover != null)
    51.        {
    52.          mover.UpdateMovementSpeed(pScore);
    53.        }
    54.      }
    55.    }
    56. }
    Code (CSharp):
    1. public class ObstacleMovementController : MonoBehaviour
    2. {
    3.    public ObstacleSpawner Spawner;
    4.    public float MovementSpeed;
    5.  
    6.    void Update()
    7.    {
    8.      transform.Translate(MovementSpeed * Time.deltaTime, 0, 0);
    9.    }
    10.  
    11.    void OnDestroy()
    12.    {
    13.      //remove the obstacle from the obstacle spawner when the gameobject or mover is destroyed
    14.      if (Spawner != null)
    15.      {
    16.        Spawner.RemoveObstacle(this.gameObject);
    17.      }
    18.    }
    19.  
    20.    public void UpdateMovementSpeed(float pScore)
    21.    {
    22.      //update movement speed based on score
    23.    }
    24. }
    Code (CSharp):
    1. public class ScoreKeeper : MonoBehaviour
    2. {
    3.     public ObstacleSpawner Spawner;
    4.     public uint Score;
    5.  
    6.     public void IncrementScore()
    7.     {
    8.         ++Score;
    9.         if (Spawner != null)
    10.         {
    11.             Spawner.UpdateSpawnRate(Score);
    12.         }
    13.     }
    14. }
     
    Last edited: Jun 18, 2016
    Chris75 likes this.
  3. Chris75

    Chris75

    Joined:
    Jan 31, 2015
    Posts:
    41
    Thanks for the reply :) However, testing your code gives this error:


    Error CS0246 The type or namespace name 'HashSet<GameObject>' could not be found (are you missing a using directive or an assembly reference?)

    I also have never seen HashSet before. So I have some reading to do on that. But any idea why I get this error?
     
  4. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    You need to add "using System.Collections.Generic;" to the top of the script. Also check the ObstacleSpawner script again. I totally forgot to check if the prefab list was null or empty.. (Fix is on line 12)
     
    Chris75 likes this.
  5. Chris75

    Chris75

    Joined:
    Jan 31, 2015
    Posts:
    41
    Will check now. I greatly appreciate the fast response and help :) Going to see if it works
    .
     
  6. Chris75

    Chris75

    Joined:
    Jan 31, 2015
    Posts:
    41
    I was able to get it working, thanks a lot Jim :)
     
  7. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Glad to hear it works. I didn't even test it myself :p
     
    Chris75 likes this.
  8. Chris75

    Chris75

    Joined:
    Jan 31, 2015
    Posts:
    41
    lol! Well maybe one day I can get to your level and write out complete code from scratch without even having Unity open!