I have been trying to write a script for an enemy were while the player is within a certain space it will teleport to a random position within a set area and fire a projectile. I want this to repeat every few seconds. However when I run the script in game it will wait a the set time execute and then the enemy will just teleport to a random position every frame rather than once every few seconds.

here is my script. any help would be much appreciated.

void Update()
{
    if (player.transform.position.x >= -45f && player.transform.position.x <= -27f &&
        player.transform.position.y >= 5f && player.transform.position.y <= 14f)
    {
       StartCoroutine(attack());
    }
}

IEnumerator attack()
{

    yield return new WaitForSeconds(movementTimer);
    transform.position = new Vector3(Random.Range(-44f, -28f), Random.Range(9.5f, 13.22f));
    
}

Assuming you want to do this with a coroutine, you can try the following:

     bool shouldTeleport = false;
	 
	 void Start()
	 {
		StartCoroutine(attack());
	 }
	 
	 void Update()
     {
         if (player.transform.position.x >= -45f && player.transform.position.x <= -27f &&
             player.transform.position.y >= 5f && player.transform.position.y <= 14f)
         {
			shouldTeleport = true;
         } else {
			shouldTeleport = false;
		 }
     }

     IEnumerator attack()
     {
		while(true){
			if (shouldTeleport){
				transform.position = new Vector3(Random.Range(-44f, -28f), Random.Range(9.5f, 13.22f));
			}
            yield return new WaitForSeconds(movementTimer);
		}
     }

This should work, however I would do this using a simpler idea, which uses a countdown timer inside the Update loop:

float movementTimer = 1f;
float countdown = 0f;

void Update()
 {
     if (player.transform.position.x >= -45f && player.transform.position.x <= -27f &&
         player.transform.position.y >= 5f && player.transform.position.y <= 14f)
     {
		countdown -= Time.deltaTime;
        if (countdown <= 0){
			transform.position = new Vector3(Random.Range(-44f, -28f), Random.Range(9.5f, 13.22f));
			countdown = movementTimer;
		}
     }
	 
 }

I didn’t actually test this code but you should be getting the idea.