Does StopCoroutine wait for the end of the coroutine's loop?

I have this code, but when the pointer “exits”, it doesnt stop the coroutine until after the loop. Is this just how it works? How do i cut off a coroutine completely?

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;

public class QuitButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {

	public AudioSource Audio1;
	public AudioSource Audio2;
	public AudioSource Audio3;
	private int SoundRandomizer;

	void Start () {
	}

	public void OnPointerEnter (PointerEventData eventData) {
		StartCoroutine (SoundDelay ());
	}

	public void OnPointerExit (PointerEventData eventData) {
		StopCoroutine (SoundDelay ());
	}

	IEnumerator SoundDelay () {
		yield return new WaitForSeconds (Random.Range (1, 6));
		if (Audio1.isPlaying == true || Audio2.isPlaying == true || Audio3.isPlaying == true)
		{
			StopCoroutine (SoundDelay ());
		}
		SoundRandomizer = Random.Range (1, 5);
		if (SoundRandomizer ==1 && Audio1.isPlaying == false && Audio2.isPlaying == false && Audio3.isPlaying == false)
		{
			Audio1.Play ();
		}
		if (SoundRandomizer == 2 && Audio1.isPlaying == false && Audio2.isPlaying == false && Audio3.isPlaying == false)
		{
			Audio2.Play ();
		}
		if (SoundRandomizer == 3 && Audio1.isPlaying == false && Audio2.isPlaying == false && Audio3.isPlaying == false)
		{
			Audio3.Play ();
		}
	}
}

StopCoroutine can only stop the coroutine at points where the coroutine yields it’s execution. Your coroutine only yields at the start. If you call StopCoroutine before the wait time has passed the following code won’t be executed.

However you use StopCoroutine (and StartCoroutine) wrong. If you pass an IEnumerator to StopCoroutine it has to be the exact same IEnumerator instance that has benn used to start the coroutine:

IEnumerator currentRoutine = null;

public void OnPointerEnter (PointerEventData eventData)
{
    // stop old one if exists
    if (currentRoutine != null)
        StopCoroutine (currentRoutine);
    // start new coroutine
    currentRoutine = SoundDelay();
    StartCoroutine (currentRoutine);
}

public void OnPointerExit (PointerEventData eventData)
{
    if (currentRoutine != null)
        StopCoroutine (currentRoutine);
    currentRoutine = null;
}

Alternatively you can use the “string version” of Start / StopCoroutine:

public void OnPointerEnter (PointerEventData eventData)
{
    StartCoroutine ("SoundDelay");
}
public void OnPointerExit (PointerEventData eventData)
{
    StopCoroutine ("SoundDelay");
}

What loop are you talking about? The StopCoroutine will only stop routines that are waiting to be executed (at least that’s my guess, I’m not sure). Notice that StopCoroutine doesn’t work if you called the routine the way you did. You need to call the routine passing the method’s name as string StartCoroutine ("SoundDelay"); and the same thing with the StopCoroutine. You can also use a flag before you play the sound to check if the pointer left the button.

You shouldn’t need to use coroutines to do this though. I’m not sure exactly what behaviour you’re expecting when you say “stop”, but you could do something like this.

public AudioClip[] audioClips;
public float minDelay = 1f;
public float maxDelay = 6f;

public void OnPointerEnter (PointerEventData eventData) 
{
	if (!audio.isPlaying)
	{
		audio.clip = Random.Range(0,audioClips.Length);
		audio.PlayDelayed(Random.Range(minDelay, maxDelay));
	}
}

public void OnPointerExit (PointerEventData eventData)
{
	audio.Stop();
}