Having trouble figuring out coroutines in C#

I’m trying to make an enemy encounter in my game where the enemy will move from left to right and shoots projectiles in 1 second intervals. I’ve got the movements working fine but I can’t get the projectiles to spawn every second. I’ve checked around and using a coroutine seems to be the way to go about but I can’t for the life of me figure out how to use them properly.

The way I have my script set up at the moment, it’s spewing out projectiles every frame because I’m calling the coroutine inside Update() but I’m not entirely sure where else I could put it if I want the script to constantly fire until the gameObject is destroyed.

GameObject proj;
IEnumerator timerSpawn()
{
   yield return new WaitForSeconds(1);
		
   /**Create a temp projectile*/
   GameObject projectile;
   //Instantiate the bullet at the position and rotation of the player
   projectile = Instantiate(proj,transform.position,transform.rotation) as GameObject;		
}

and then in my Update()

void Update () 
{
   StartCoroutine(timerSpawn());
   ...
   ...
}

I’m fairly new to C# and Unity in general so if anyone could help me out on how to go about implementing this, I’d greatly appreciate it.

If I understand things right, you probably just want to start a looping coroutine from Start() or Awake(). Something like this:

bool keepSpawning = true;

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

IEnumerator TimerSpawn()
{
    while (keepSpawning)
    {
        Debug.Log("Spawn something");
        yield return new WaitForSeconds(1f);
    }
}

A coroutine will only fire once per call to StartCoroutine(), but as you can see from the example it’s possible to keep the function going with a loop. The function will pause on every yield, and will continue execution after the yield.

You can probably figure out where to take it from there.

Don’t forget that you can always check the official script reference:

If this is too confusing, remember that you can also use Invoke() or InvokeRepeating().

You should use a boolean flag to stop firing coroutines while the last one has not finished:

bool firing = false; // flag "I'm shooting alredy!"

void Update()
{ // only start a new coroutine when the previous one has finished:
  if (!firing) StartCoroutine(timerSpawn());
  ...
}

GameObject proj;
IEnumerator timerSpawn()
{
   firing = true; // the coroutine is running!
   yield return new WaitForSeconds(1);
   /**Create a temp projectile*/
   GameObject projectile;
   //Instantiate the bullet at the position and rotation of the player
   projectile = Instantiate(proj,transform.position,transform.rotation) as GameObject;
   firing = false; // coroutine ended
}

Additionally, you must give velocity to the projectile, or it will not move. Another issue: if created at player position, it will collide with the player. You should usually have an empty game object (childed to the player) at the desired spawn point, and pass this position to Instantiate.