Coroutine Behavior Error

I have two coroutines that alternate when they run. When move_away()'s conditions are met, move_to() is disabled and the StartCoroutine function is called, and vice versa when move_to()'s conditions are met. This should cause the two to loop infinitely, but the ‘loop’ will run 3-10 times before one of them just fails to run at a StartCoroutine call.

I trimmed out everything not directly affecting the coroutines or the relevant variables. It is intended to have an object travel from the edge of the screen to the player, until other factors affect it.
Through testing, I’ve figured out that it always stops right after one of the StartCoroutine() functions are called.

public int is_move = 0; // -1 = move_away, 0 = not moving, 1 = move_to
	public float walkSpeed = 0.1f;

	private IEnumerator cor_away;
	private IEnumerator cor_to;
	private IEnumerator cor_circle;
	private IEnumerator cor_lunge;

	private Rigidbody2D body;
	private GameObject player;
	private Vector3 player_pos;

	void Start () {
		cor_away = move_away();
		cor_to = move_to();
	}

	void FixedUpdate() {
		player_pos = player.transform.position;

		//Checks for moving out of bounds
		if (tooFar () & is_move != 1) {
			StopCoroutine (cor_away);
			is_move = 1;
			StartCoroutine (cor_to);
		} else if (tooClose () & is_move != -1) {
			StopCoroutine (cor_to);
			is_move = -1;
			StartCoroutine (cor_away);
		}
	}

	IEnumerator move_to(){
		while (is_move == 1) {
			transform.position = Vector3.MoveTowards (transform.position, player_pos, walkSpeed);
			if (tooClose()) {
				is_move = 0;
			}
			yield return new WaitForSeconds(0.01f);
		}
	}

	IEnumerator move_away(){
		while (is_move == -1) {
			transform.position = Vector3.MoveTowards (transform.position, player_pos, -walkSpeed);
			if (tooFar()) {
				is_move = 0;
			}
			yield return new WaitForSeconds(0.01f);
		}
	}

	private Vector2 calc_dist(){
		Vector3 diff = player_pos - transform.position;
		float x = Mathf.Abs (diff.x);
		float y = Mathf.Abs (diff.y);
		return new Vector2 (x, y);
	}

	public bool tooFar () {
		//Checks if the enemy is too close to the edge of the screen. Returns true if it is.
		//Checks the position based on x and y coordinates

		Vector2 dist = calc_dist();
		float dX = dist.x;
		float dY = dist.y;

		if (dX > max_dist_h || dY > max_dist_v) {
			return true;
		} else {
			return false;
		}
	}

	public bool tooClose(){
		//Checks if the enemy is too close to the player. Returns true if it is.
		//Checks the position as a circle around the player (uses magnitude instead of coordinate distance)

		float dist_mag = calc_dist ().magnitude;
		if (dist_mag < min_dist) { 
			return true;
		} else {
			return false;
		}
	}
}

You can not re-use an IEnumerator once it has been started. It also looks like you have some misunderstanding about how coroutines work. Once you pass the IEnumerator (that your generator method creates) to StartCoroutine, Unity will store the enumerator internally and the coroutine scheduler will take care of it. So it is automatically scheduled every frame depending on what value was yielded.

Once started coroutines run on their own. So calling starting a coroutine every frame doesn’t make any sense as it would create a new coroutine each frame. Starting and stopping coroutines all the time is not a good idea. It would be better to simply have your two loops from your two coroutines in a single coroutine. Start the coroutine once at “Start()”.

Next thing is you try to wait for 0.01f seconds. However the minimum waiting time is the frametime. You can’t wait for a smaller amount. So at a framerate of 60 fps the frame time would be 0.016666. In most cases you just want to wait for the next frame. To do this you should use yield return null;.

Finally FixedUpdate has only relevance if you’re dealing with continuous forces applied to a rigidbody. Pretty much everything else should be done in Update.

So your coroutine could simply look like this:

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

IEnumerator AdjustDistance()
{
    while (true)
    {
        if (tooFar () & is_move != 1) {
            is_move = 1;
        } else if (tooClose () & is_move != -1) {
            is_move = -1;
        }
        transform.position = Vector3.MoveTowards (transform.position, player_pos, walkSpeed * is_move * Time.deltaTime);
        yield return null;
    }
}

“walkSpeed” should be defined in worldunits per second. This coroutine would do the same what your two coroutines should have done.